<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Codesphere on Medium]]></title>
        <description><![CDATA[Stories by Codesphere on Medium]]></description>
        <link>https://medium.com/@codesphere-cloud?source=rss-86282414923b------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*an7W8VpGD0t9aWY-qsa8Ew.png</url>
            <title>Stories by Codesphere on Medium</title>
            <link>https://medium.com/@codesphere-cloud?source=rss-86282414923b------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Wed, 27 May 2026 09:49:46 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@codesphere-cloud/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Deep Dive: Build your own VS Code extension]]></title>
            <link>https://codesphere-cloud.medium.com/deep-dive-build-your-own-vs-code-extension-aa502fe3563e?source=rss-86282414923b------2</link>
            <guid isPermaLink="false">https://medium.com/p/aa502fe3563e</guid>
            <category><![CDATA[vscode]]></category>
            <category><![CDATA[vscode-extension]]></category>
            <category><![CDATA[tutorial]]></category>
            <dc:creator><![CDATA[Codesphere]]></dc:creator>
            <pubDate>Mon, 10 Jun 2024 16:49:53 GMT</pubDate>
            <atom:updated>2024-06-10T16:49:53.427Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/600/1*1pgCe0axLZSBaTl_Pikj5A.png" /></figure><p>Visual Studio Code is a powerful code editor known for its extensibility. Users can install various extensions to fit their needs, and if something isn’t available, they can build their own extensions to enhance productivity. To do this, an extension author needs to be familiar with the VS Code API and the development workflow for creating extensions.</p><p>In this blog post, we will show you the framework we used to build an extension using a webview to display anything you like. We will guide you through the development of an extension, where you can modify the project to do specific tasks, and finally, we will show you how to officially publish an extension on the VS Code Marketplace.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*E9F9eCCju8knauW5wjTe1Q.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*qK4f6DJQPF_Ia69zSKnb2Q.png" /></figure><h3>Preparation</h3><p>The VS Code extension will be a TypeScript project, and for the webview, we will use Svelte as the frontend framework. We have prepared a VS Code extension development template so that you can clone this repository and get started right away:</p><p>GitHub repository: <a href="https://github.com/codesphere-cloud/vscode-extension-template?ref=codesphere.ghost.io">https://github.com/codesphere-cloud/vscode-extension-template</a></p><pre>git clone https://github.com/codesphere-cloud/vscode-extension-template<br>cd vscode-extension-template<br>npm i</pre><p>This will download the VS Code template and install all the dependencies you need for developing your extension.</p><p>That’s it. You are ready to test and build your extension. First, we want to make sure that the tutorial extension works. When developing an extension, we want to test every change right away, and testing should be a smooth workflow.</p><p>We can open a debug VS Code window called Extension-Development-Host to test our extension. First, we run a command to compile our extension while working on it.</p><pre>npm run watch</pre><p>Tip: open a new Terminal with this Keyboard combination: Ctrl + Shift + `</p><p>This compiles our extension every time we are changing our project. now we open either src/SidebarProvider.ts or src/extension.ts file and push F5 to open a new extension-developing-host. an this is the result:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*t3AvwH5GMAOB87pwq9f09g.png" /></figure><p>The template extension we provide adds a view to the activity bar on the side with a webview a user can interact with. We kept this tutorial template as simple as possible, so you can follow along with this tutorial and get to know the project better while adding new features to it.</p><p>This tutorial focuses on creating a webview in the side panel of VS Code, but you can do much more than that. In the last section of this blog post, we will list a bunch of links to useful resources for further reference.</p><p>Now, we will build a GitHub Copilot-style chat interface together, but with a locally installed Llama.cpp.</p><h3>Project idea</h3><p>The idea is to replicate the GitHub Co-Pilot chat interface on VS Code but with a locally self-hosted Llama.cpp instance. The use case for this would be if you are working on a project which data should not be exposed to other services. Such an approach of using AI would be data compliant.</p><p>We need to set up our local Llama.cpp instance and use the server example of this repository to host our own OpenAI compatible chat completion, so we have a nice to use API. Now, we guide you through the process of setting up your locally installed Llama.cpp instance.</p><p>Firstly, you need to clone the GitHub repository of llama.cpp and build the project with make . Make sure that you are in the root directory of the extension:</p><pre>git clone https://github.com/ggerganov/llama.cpp<br>cd llama.cpp/<br>make</pre><p>Depending on your local resources this command might take while. After completion we can continue to set up the OpenAI compatible server:</p><pre>cd examples/server<br>make server</pre><p>Like before this might take a while. After building the server we need to download our model we want to use. The important thing is to use models in the .gguf format. You can browse avalable models on HuggingFace: <a href="https://huggingface.co/models?library=gguf&amp;sort=trending&amp;ref=codesphere.ghost.io">https://huggingface.co/models?library=gguf&amp;sort=trending</a></p><p>We chose the qwen2–7b-instruct-q8_0.gguf model: <a href="https://huggingface.co/Qwen/Qwen2-7B-Instruct-GGUF/tree/main?ref=codesphere.ghost.io">https://huggingface.co/Qwen/Qwen2-7B-Instruct-GGUF/tree/main</a></p><p>It is 8 GB and to download it takes a while. You can download it to your models/ directory in your root:</p><pre>cd models/<br>wget https://huggingface.co/Qwen/Qwen2-7B-Instruct-GGUF/resolve/main/qwen2-7b-instruct-q8_0.gguf?download=true</pre><p>Simply replace this link with the link to the model you want to use. Now, you need to wait until this model is downloaded.</p><p>When downloading is finished you can use this model right away. Execute this command in the root directory of llama.cpp:</p><pre>chmod a+x ./server<br>./server -m models/qwen2-7b-instruct-q8_0.gguf -c 2048</pre><p>And again, if you chose an other model replace the path to the model to the right file.</p><p>You can now use the Llama.cpp interface on localhost:8080</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*zfgVLipzgGwHkJzFBy32ow.png" /></figure><p>You can for sure optimize the performance of the model running now on your localhost, but lets stick with this for this tutorial because we want to build a VS Code extension.</p><p>Since we are using the API we wont need that UI. Here is a documentation about the API: <a href="https://github.com/ggerganov/llama.cpp/tree/master/examples/server?ref=codesphere.ghost.io#API-Endpoints">https://github.com/ggerganov/llama.cpp/tree/master/examples/server#API-Endpoints</a></p><h3>Features to add</h3><p>Inside our sidepanel extension we want to add these features:</p><ul><li>start your AI model out of VS Code</li><li>place an input field for your prompts</li><li>use the completion endpoint of our model to generate a response</li><li>display the response to our webview</li></ul><p>We want to keep this extension simple and if you want to you can take the challenge and improve it as you like! 🤗</p><h3>Creating a Button to Start and Stop Llama.cpp</h3><p>Let’s create buttons so that we don’t have to type the command in the terminal every time we want to use our Llama instance. Additionally, it would be convenient to have a button to stop the model from running, as we don’t want to manually find out the PID in order to kill the process.</p><p>The idea is to add icons to the top-right corner. Perhaps you’re familiar with some extensions that have these small icons in the top-right corner (e.g., GitHub Co-Pilot).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/483/1*ZW_64A093fktpgtGPt1PZQ.png" /></figure><p>To add these buttons, we need to modify our package.json file first. The package.json file in our project is an important file filled with various metadata about your extension. This file serves as one of the main entry points to your extension. Inside the package.json, there is a field called menus. We will add two additional icons to our existing icon by appending these objects to that array.</p><pre>&quot;menus&quot;: {<br>      &quot;view/title&quot;: [<br>        {<br>          &quot;command&quot;: &quot;tutorial.tutorial&quot;,<br>          &quot;when&quot;: &quot;view == tutorial-sidebar&quot;,<br>          &quot;group&quot;: &quot;navigation&quot;<br>        },<br>        {<br>          &quot;command&quot;: &quot;tutorial.start&quot;,<br>          &quot;when&quot;: &quot;view == tutorial-sidebar &amp;&amp; !tutorial.modelIsRunning&quot;,<br>          &quot;group&quot;: &quot;navigation&quot;<br>        },<br>        {<br>          &quot;command&quot;: &quot;tutorial.stop&quot;,<br>          &quot;when&quot;: &quot;view == tutorial-sidebar &amp;&amp; tutorial.modelIsRunning&quot;,<br>          &quot;group&quot;: &quot;navigation&quot;<br>        }<br>      ]<br>    },</pre><p>In the when attribute, you can specify conditions for when the icons should be displayed. We can control variables through the VS Code API. We want the start icon to be displayed when the model is not running, and when it is running, we want to display the stop button.</p><p>We aim to use small icons for these commands. There is a variety of internal icons available for use: <a href="https://code.visualstudio.com/api/references/icons-in-labels?ref=codesphere.ghost.io#icon-listing">Icon Listing</a></p><p>In our package.json file, there is a commands field where we can add such icons. You can simply copy this snippet and replace it with the existing one:</p><pre>&quot;commands&quot;: [<br>      {<br>        &quot;command&quot;: &quot;tutorial.tutorial&quot;,<br>        &quot;title&quot;: &quot;tutorial&quot;,<br>        &quot;icon&quot;: &quot;$(log-out)&quot;,<br>        &quot;category&quot;: &quot;Tutorial command&quot;<br>      },<br>      {<br>        &quot;command&quot;: &quot;tutorial.start&quot;,<br>        &quot;title&quot;: &quot;Start&quot;,<br>        &quot;icon&quot;: &quot;$(play)&quot;,<br>        &quot;category&quot;: &quot;Tutorial command&quot;<br>      },<br>      {<br>        &quot;command&quot;: &quot;tutorial.stop&quot;,<br>        &quot;title&quot;: &quot;Stop&quot;,<br>        &quot;icon&quot;: &quot;$(stop)&quot;,<br>        &quot;category&quot;: &quot;Tutorial command&quot;<br>      }<br>    ]</pre><p>Now we save with Ctrl + S and navigate to our Extension Development Host, then press Ctrl + R to refresh the window. You should now see the icons displayed in the top-right corner.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/483/1*KtzoJvHjfW3YMLPLBqJuJg.png" /></figure><p>Perhaps you noticed that the stop button is not displayed. This is because of the condition we provided in the package.json.</p><p>Now let’s code the commands that are executed when clicking on these icons. We need to open the src/extension.ts file to register our commands with the extension. We register the commands in the activation function of this file. In our package.json, there is a field named activationEvents where we can specify when the activation function is executed.</p><pre>&quot;activationEvents&quot;: [<br>    &quot;onStartupFinished&quot;<br>  ],</pre><p>The activation event is set to onStartupFinished. This means the activation function is executed when VS Code is fully loaded. You can copy this code snippet and paste it into extension.ts:</p><pre>context.subscriptions.push(<br>  vscode.commands.registerCommand(&#39;tutorial.start&#39;, async () =&gt; {<br>    vscode.commands.executeCommand(&#39;setContext&#39;, &#39;tutorial.modelIsRunning&#39;, true);<br>  })<br>);</pre><pre>context.subscriptions.push(<br>  vscode.commands.registerCommand(&#39;tutorial.stop&#39;, async () =&gt; {<br>    vscode.commands.executeCommand(&#39;setContext&#39;, &#39;tutorial.modelIsRunning&#39;, false);<br>  })<br>);</pre><p>Now, when you reload the Extension Development Host with Ctrl + R, you can test these icons, and you will notice that after clicking, the icon changes. This is the result of using the condition. We can change the context for the modelIsRunning variable during the runtime of your extension.</p><p>Now, we actually want to add functionality to our buttons. We can do that by simply extending the registerCommand() code block with the logic we want to have.</p><p>We want to start our LLama.cpp instance when clicking start and stop it when clicking stop. We need to execute these bash commands. You can again simply copy and paste this code snippet into the code you already have:</p><p>a) start Llama.cpp on localhost:8080:</p><pre>context.subscriptions.push(<br>  vscode.commands.registerCommand(&#39;tutorial.start&#39;, async () =&gt; {<br>  <br>    const extension = vscode.extensions.getExtension(&#39;Tutorial.tutorial&#39;)?.extensionPath;</pre><pre>// Your Llama.cpp folder has to be inside the extension folder<br>    const serverPath = path.join(extension, &#39;llama.cpp&#39;, &#39;server&#39;);<br>    const modelPath = path.join(extension, &#39;llama.cpp&#39;, &#39;models&#39;, &#39;qwen2-7b-instruct-q8_0.gguf&#39;);<br>    const bashcommand = `${serverPath} -m ${modelPath} -c 2048`;<br>    const test = &#39;echo hi&#39;;<br>    exec (bashcommand, (error, stdout, stderr) =&gt; { <br>        if (error) {<br>            console.error(`exec error: ${error}`);<br>            return;<br>        }<br>        if (stderr) {<br>            console.error(`stderr: ${stderr}`);<br>            return;<br>        }<br>        console.log(`stdout: ${stdout}`);<br>    });<br>    vscode.commands.executeCommand(&#39;setContext&#39;, &#39;tutorial.modelIsRunning&#39;, true);<br>  })<br>);</pre><p>Note: We will save the PID (process ID) of the process to our extension’s globalStorage to ensure that we can kill this process with our extension’s stop button. The globalStorage can be used for state management in our extension.</p><p>b) stop Llama.cpp server:</p><pre>context.subscriptions.push(<br>    vscode.commands.registerCommand(&#39;tutorial.stop&#39;, async () =&gt; {<br>        const pid = context.globalState.get(&quot;codesphere.runningPID&quot;);<br>        console.log(pid)</pre><pre>        const bashcommand = `kill ${pid as number + 1}`;</pre><pre>        const childProcess = exec(bashcommand, (error, stdout, stderr) =&gt; {<br>            if (error) {<br>                console.error(`exec error: ${error}`);<br>                return;<br>            }</pre><pre>            if (stderr) {<br>                console.error(`stderr: ${stderr}`);<br>                return;<br>            }</pre><pre>            console.log(`stdout: ${stdout}`);<br>        });</pre><pre>        context.globalState.update(&quot;codesphere.runningPID&quot;, &quot;&quot;);<br>        vscode.commands.executeCommand(&#39;setContext&#39;, &#39;tutorial.modelIsRunning&#39;, false);<br>    })<br>);</pre><p>We loaded the PID from our globalStorage and used it to terminate the correct process. And there we have it! Now we can start and stop our local Llama.cpp model as needed.</p><p>Tip: We actually have a webview developer console inside the extension development host to debug our extension. You can open it as follows:</p><ul><li>Ctrl + Shift + P</li><li>select Developer: Open Webview Developer Tools</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*eIWs9AyefmUtsYvnzES_WA.png" /></figure><h3>Place an input field to our webview</h3><p>The user needs to place the prompt somewhere. Let’s create the UI for that within our Svelte file. For that, we simply need HTML, CSS, and JavaScript for the functionality.</p><p>In our Svelte file, we have a &lt;script&gt; tag for JavaScript code and a &lt;style&gt; tag for CSS. In the rest of the file, you can place the HTML code. Let&#39;s keep it simple, and if you want, you can practice your UI/UX design by enhancing this code as you like.</p><p>Add the following two code snippets to src/webviews/components:</p><p>a) CSS</p><pre>.prompt-container {<br>        display: flex;<br>        align-items: center;<br>        padding: 10px;<br>        width: 100%;<br>        max-width: 600px;<br>        margin: 0 auto;<br>        position: fixed;<br>        bottom: 0;<br>        left: 0;<br>    }</pre><pre>    .prompt-input {<br>        flex: 1;<br>        padding: 10px;<br>        border: none;<br>        outline: none;<br>        font-size: 16px;<br>    }</pre><pre>    .prompt-button {<br>        display: flex;<br>        justify-content: center;<br>        align-items: center;<br>        padding: 10px 20px;<br>        font-size: 16px;<br>        border: none;<br>        cursor: pointer;<br>        border-radius: 4px;<br>        margin-left: 10px;<br>        width: 50px;<br>        height: 50px;<br>        align-self: end;  <br>    }</pre><p>b) HTML</p><pre>&lt;div class=&quot;prompt-container&quot;&gt;<br>        &lt;textarea type=&quot;text&quot; placeholder=&quot;Ask your model something about your code&quot; wrap=&quot;hard&quot; class=&quot;prompt-input&quot;&gt;&lt;/textarea&gt;<br>        &lt;button class=&quot;prompt-button&quot;&gt;<br>            &lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;100px&quot; height=&quot;100px&quot; viewBox=&quot;0 0 16 16&quot;&gt;<br>                &lt;path fill=&quot;currentColor&quot; fill-rule=&quot;evenodd&quot; d=&quot;m4.25 3l1.166-.624l8 5.333v1.248l-8 5.334l-1.166-.624zm1.5 1.401v7.864l5.898-3.932z&quot; clip-rule=&quot;evenodd&quot;/&gt;<br>            &lt;/svg&gt;<br>        &lt;/button&gt;<br>    &lt;/div&gt;</pre><p>And this is the result:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/521/1*iDZRYagTDp-zdy6JYVXSvw.png" /></figure><p>As you can see, we didn’t add a color to our button, but it’s blue. That’s because in our project, we have some standard VS Code styles imported. You can find the styles in the media directory of our project.</p><h3>Split the webview to two different sections</h3><p>It’s time to split up our webview since the HelloWorld template has nothing to do with our chat interface. We can have multiple webviews in our sidebar simultaneously, like an accordion, where you can open and close the different webviews as you like.</p><pre>&quot;views&quot;: {<br>      &quot;tutorial-sidebar-view&quot;: [<br>        {<br>          &quot;type&quot;: &quot;webview&quot;,<br>          &quot;id&quot;: &quot;tutorial-sidebar&quot;,<br>          &quot;name&quot;: &quot;Tutoial&quot;,<br>          &quot;icon&quot;: &quot;media/tutorial.svg&quot;,<br>          &quot;contextualTitle&quot;: &quot;Tutorial&quot;<br>        },<br>        {<br>          &quot;type&quot;: &quot;webview&quot;,<br>          &quot;id&quot;: &quot;tutorial-chat&quot;,<br>          &quot;name&quot;: &quot;Chat&quot;,<br>          &quot;icon&quot;: &quot;media/tutorial.svg&quot;,<br>          &quot;contextualTitle&quot;: &quot;Chat&quot;<br>        }<br>      ]<br>    },</pre><p>With that simple trick we created a second webview window inside our sidebar:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/521/1*4LlMXFvLkORTjArGRiGtvw.png" /></figure><p>The content in our new chat window is loading infinitely because we haven’t registered content for that window in our extension. Let’s change that by adding code in src/extension.ts:</p><pre>const chatProvider = new ChatProvider(context.extensionUri, context);<br>context.subscriptions.push(<br>  vscode.window.registerWebviewViewProvider(<br>  &quot;tutorial-chat&quot;,<br>  chatProvider<br>  )<br>);</pre><p>Now, when you refresh the extension development host, you will see that the content is loaded into the second webview. The reason this works without adding extra files is that we provided the necessary files in the template. Here is a list of the files you need to add to register this new webview:</p><ul><li>ChatProvider.ts in /src</li><li>Chat.svelte in webviews/components</li><li>chat.ts in webview/pages</li></ul><p>If you are about to create another webview and you are using our SidebarProvider.ts as a template for that, you need to change the compiled JavaScript and CSS files to the correct ones.</p><pre>const styleResetUri = webview.asWebviewUri(<br>      vscode.Uri.joinPath(this._extensionUri, &quot;media&quot;, &quot;reset.css&quot;)<br>    );<br>    const scriptUri = webview.asWebviewUri(<br>      // change here<br>      vscode.Uri.joinPath(this._extensionUri, &quot;out&quot;, &quot;compiled/chat.js&quot;)<br>    );<br>    const styleMainUri = webview.asWebviewUri(<br>      // change here<br>      vscode.Uri.joinPath(this._extensionUri, &quot;out&quot;, &quot;compiled/chat.css&quot;)<br>    );<br>    const styleVSCodeUri = webview.asWebviewUri(<br>      vscode.Uri.joinPath(this._extensionUri, &quot;media&quot;, &quot;vscode.css&quot;)<br>    );</pre><h3>Add functionality to our chat-interface</h3><p>Now we have our UI, but we need the logic for handling our prompts and displaying the response. In order to do that, we need to send our prompt to our model via the API and send the response to our webview so that we can display it. It follows the same pattern when implementing logic for our extension:</p><ol><li>Send data from the webview to our extension via the postMessage method.</li><li>Handle the message within our extension’s code (e.g., ChatProvider.ts) inside the switch-case block.</li><li>Send back data to our webview with the postMessage method.</li></ol><p>First, we define a function to forward our prompt to the extension and add this prompt to our chat interface. You can replace the someMessage() function with the following code:</p><pre>function someMessage() {<br>    // Clear the textarea<br>    document.getElementById(&#39;promptInput&#39;).value = &#39;&#39;;</pre><pre>    // add textblock to chat interface<br>    const chat = document.createElement(&#39;div&#39;);<br>    let randomId = generateRandomId();<br>    chat.innerHTML = `&lt;div style=&quot;  background-color: #00BCFF; <br>                                    color: black; <br>                                    padding: 10px; <br>                                    margin: 10px; <br>                                    border-radius: 10px; <br>                                    display: inline-block;&quot;&gt;${prompt}&lt;/div&gt;`;<br>    document.getElementById(&#39;chatContainer&#39;).appendChild(chat);</pre><pre>    // Create response div<br>    const responseDiv = document.createElement(&#39;div&#39;);<br>    // styling<br>    responseDiv.style = &quot;background-color: #6F40D3; color: black; padding: 10px; margin: 10px; border-radius: 10px; display: inline-block;&quot;;<br>    responseDiv.id = randomId;<br>    document.getElementById(&#39;chatContainer&#39;).appendChild(responseDiv);</pre><pre>    vscode.postMessage({<br>        type: &#39;prompt&#39;,<br>        value: {<br>            prompt: prompt,<br>            id: randomId<br>        }<br>    });<br>}</pre><p>The postMessage() method will send a message to our extension, and the type property of the message body will serve as the identifier for which case in our switch-case code block will be executed within the ChatProvider.ts.</p><pre>webviewView.webview.onDidReceiveMessage(async (data) =&gt; {<br>      switch (data.type) {<br>        case &quot;prompt&quot;: {<br>          if (!data.value) {<br>            return;<br>          }</pre><pre>          let prompt = data.value.prompt;<br>          let id = data.value.id;</pre><pre>          const Test = async (prompt: string, id: any) =&gt; {<br>            try {<br>              let response = await fetch(&quot;http://127.0.0.1:8080/completion&quot;, {<br>                method: &#39;POST&#39;,<br>                headers: {<br>                  &#39;Content-Type&#39;: &#39;application/json&#39;,<br>                },<br>                body: JSON.stringify({<br>                  prompt,<br>                  n_predict: 30,<br>                  stream: true,<br>                }),<br>              });</pre><pre>              if (!response.ok) {<br>                throw new Error(`HTTP error! status: ${response.status}`);<br>              }</pre><pre>              if (!response.body) {<br>                throw new Error(&#39;Response body is null&#39;);<br>              }</pre><pre>              const reader = response.body.getReader();<br>              const decoder = new TextDecoder();<br>              let result = &#39;&#39;;</pre><pre>              while (true) {<br>                const { done, value } = await reader.read();<br>                if (done) {<br>                  break;<br>                }<br>                result += decoder.decode(value, { stream: true });</pre><pre>                const lines = result.split(&#39;\n&#39;);<br>                for (const line of lines) {<br>                  if (line.startsWith(&#39;data:&#39;)) {<br>                    try {<br>                      const json = JSON.parse(line.substring(5).trim());<br>                      console.log(json.content);<br>                      let token = json.content;<br>                      this._view?.webview.postMessage({<br>                        type: &quot;response&quot;,<br>                        value: token,<br>                        id: id<br>                      });<br>                    } catch (e) {<br>                      console.error(&#39;Error parsing JSON:&#39;, e);<br>                    }<br>                  }<br>                }<br>                result = lines[lines.length - 1];<br>              }</pre><pre>              this._view?.webview.postMessage({<br>                type: &quot;response&quot;,<br>                value: &quot;done&quot;,<br>                id: id<br>              });<br>            } catch (error) {<br>              console.error(&#39;Error:&#39;, error);<br>            }<br>          };</pre><pre>          await Test(prompt, id);</pre><pre>          break;<br>        }<br>      }<br>    });</pre><p>This will handle our request to our running LLM. We call it in stream mode, which means that every token is sent separately back. Every time we get a token, we send this token back to our extension via the postMessage method so that we can add it to our chat interface within the webview&#39;s code.</p><pre>onMount(() =&gt; {<br>    window.addEventListener(&#39;message&#39;, event =&gt; {<br>        const message = event.data; // The JSON data our extension sent<br>        console.log(`message received: ${JSON.stringify(message)}`);<br>        switch (message.type) {<br>            case &#39;response&#39;:<br>                if (message.value === &#39;done&#39;) {<br>                    // Mark the end of the response<br>                    break;<br>                }<br>                let responseDiv = document.getElementById(message.id)<br>                responseDiv.innerHTML += message.value;<br>                <br>                break;<br>        }<br>    });<br>});</pre><p>Now we can have a chat with our locally hosted LLM.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/367/1*WzS2H6ZHmFrK8fIgiItFyQ.png" /></figure><h3>Publish an extension</h3><p>When we decide that our extension is ready to be published, we can do so using the vsce CLI tool for managing VS Code extensions.</p><p>Fist we need to install the vsce CLI:</p><pre>npm install -g @vscode/vsce</pre><p>Packaging your project to a .vsix file is the easiest way to share your extension. You need to run this command in the root directory of your project:</p><pre>vsce pack</pre><p>However, since it’s not always trustworthy to share files directly, we might want to publish our extension in the official <a href="https://marketplace.visualstudio.com/vscode?ref=codesphere.ghost.io">VS Code Extension Marketplace</a>. Since Microsoft’s official documentation for publishing extensions is clear, we will just reference their documentation here: <a href="https://code.visualstudio.com/api/working-with-extensions/publishing-extension?ref=codesphere.ghost.io">Publishing Extension</a>.</p><p>Once you’ve completed everything and your extension is accepted, it will be listed and available for other users to install.</p><h3>Further links</h3><p>This is a list of links which were useful to us when building our own VS Code extension (will be updated when finding good reference):</p><ul><li>Youtube tutorial (Ben Awad): <a href="https://www.youtube.com/watch?v=a5DX5pQ9p5M&amp;list=WL&amp;index=1&amp;ref=codesphere.ghost.io">https://www.youtube.com/watch?v=a5DX5pQ9p5M&amp;list=WL&amp;index=1</a></li><li>Genral information: <a href="https://code.visualstudio.com/api?ref=codesphere.ghost.io">https://code.visualstudio.com/api</a></li><li>Commands: <a href="https://code.visualstudio.com/api/extension-guides/command?ref=codesphere.ghost.io">https://code.visualstudio.com/api/extension-guides/command</a></li><li>Webviews: <a href="https://code.visualstudio.com/api/extension-guides/webview?ref=codesphere.ghost.io">https://code.visualstudio.com/api/extension-guides/webview</a></li><li>Build-in commands: <a href="https://code.visualstudio.com/api/references/commands?ref=codesphere.ghost.io">https://code.visualstudio.com/api/references/commands</a></li><li>Activation events: <a href="https://code.visualstudio.com/api/references/activation-events?ref=codesphere.ghost.io">https://code.visualstudio.com/api/references/activation-events</a></li><li>about package.json: <a href="https://code.visualstudio.com/api/references/extension-manifest?ref=codesphere.ghost.io">https://code.visualstudio.com/api/references/extension-manifest</a></li><li>publishing extensions: <a href="https://code.visualstudio.com/api/working-with-extensions/publishing-extension?ref=codesphere.ghost.io">https://code.visualstudio.com/api/working-with-extensions/publishing-extension</a></li></ul><h3>Conclusion</h3><p>This tutorial serves as a comprehensive guide for creating a Visual Studio Code extension from scratch. We utilized the template provided to build an extension that interacts with a running Llama.cpp instance on localhost:8080. While this tutorial covers a lot, there are many more possibilities to explore when creating VS Code extensions, but covering all of them would be too much for one blog post.</p><p>If you’re interested in building your own VS Code extension, you can join our Discord Server to connect with fellow software developers, Codesphere users, and the Codesphere team: <a href="https://discord.gg/codesphere?ref=codesphere.ghost.io">Discord Server</a>.</p><p>Furthermore, if you want to improve this tutorial extension, there are plenty of things you can do! It’s a great project to practice your coding skills and your VS Code extension creation skills. Here are some ideas for improvement:</p><ul><li>Persistent Chats: Implement a feature to save chat histories or conversations between sessions.</li><li>Creating a HuggingFace LLM Browser as a Separate Webview to Download Models: Develop a separate webview interface where users can browse and download models from HuggingFace.</li><li>Fine-Tune Prompt Settings or Create a UI for User Settings: Allow users to fine-tune prompt settings or provide a user-friendly UI for configuring settings related to the extension.</li><li>Improve UI/UX: Enhance the user interface and experience of the extension to make it more intuitive and visually appealing.</li><li>User-Friendly Installation of Llama.cpp: Simplify the installation process of Llama.cpp for users, possibly by automating or providing clear instructions within the extension.</li><li>Improve Model Performance Depending on User’s Hardware: Implement optimizations to enhance the performance of the model, taking into account the hardware specifications of the user’s machine.</li><li>Implement Error Handling: Develop mechanisms to handle errors gracefully, providing meaningful error messages and guiding users on how to resolve issues when they occur.</li><li>Cross-Platform Compatibility: Ensure that the extension functions smoothly on the Mac, Linux, and Windows operating systems.</li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=aa502fe3563e" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Self-host AI interface builder OpenUI on Codesphere]]></title>
            <link>https://codesphere-cloud.medium.com/self-host-ai-interface-builder-openui-on-codesphere-5a5ed852a98a?source=rss-86282414923b------2</link>
            <guid isPermaLink="false">https://medium.com/p/5a5ed852a98a</guid>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[ui-design]]></category>
            <category><![CDATA[self-hosted]]></category>
            <dc:creator><![CDATA[Codesphere]]></dc:creator>
            <pubDate>Tue, 23 Apr 2024 08:57:29 GMT</pubDate>
            <atom:updated>2024-04-23T08:57:29.918Z</atom:updated>
            <content:encoded><![CDATA[<p>AI tools helping with any and all parts of software development have been popping up left and right. The promise replacing coding tasks that are typically both mundane and require a learning curve is very appealing.</p><p>With OpenUI you can create frontends in most common programming languages i.e. HTML, React, Svelte, Vue or web components with simple natural language prompts. The created draft is then refined by the AI by adding comments to elements just like you’d be collaborating with a design team in Figma. And the best? It works both with managed AI endpoints from OpenAI and self hosted models available via Ollama.</p><h3>Step 1: Create workspace</h3><p>If you haven’t created an account navigate to codesphere.com and sign up. Next you want to create a workspace, if you plan on using a self hosted model via Ollama it needs to be equipped with one of our GPU plans. Otherwise a smaller plan should be sufficient.</p><h3>Step 2: Install Ollama</h3><p>If you want to use OpenAI instead of a self hosted model you can skip this step.</p><p>We will need to follow a slightly altered version of the official installation guide as we need to install Ollama in our local home/user/app directory. Open a terminal an type:</p><pre>sudo curl -L https://ollama.com/download/ollama-linux-amd64 -o /home/user/app/ollama</pre><p>Then provide execution rights to the downloaded file via:</p><pre>sudo chmod +x /home/user/app/ollama</pre><h3>Step 3: Clone OpenUI Repository</h3><p>Next get the source code for the UI interface builder.</p><pre>git clone https://github.com/wandb/openui.git</pre><p>This will create a new folder in your app directory with the frontend and backend code for the UI builder.</p><h3>Step 4: Install required Python version and configure virtual environment env variables</h3><p>Codesphere pre-installs Python but for this project we will need a newer version. Firstly we need to configure our pyenv — this will make sure our installed Python version is persistent across workspace restarts.</p><ol><li>Navigate to setup/env vars and set PYENV_ROOT to /home/user/app/.pyenv</li><li>Grab your workspace dev domain via echo $WORKSPACE_DEV_DOMAIN and copy to clipboard</li><li>Set OPENUI_HOST to the value you just copied</li><li>Set OPENAI_API_KEY to xxx (for local Ollama models) or to your actual Open AI API key</li><li>Set OPENUI_ENVIRONMENT to local (please note for production use you&#39;ll want to set this to production and set up the GitHub SSO app for session handling)</li><li>Open a new terminal (existing terminals don’t get updated env vars)</li><li>Type pipenv install --python 3.10.0 and confirm with Y - this will take a few minutes</li><li>Activate with pipenv shell</li></ol><p>Verify that your Python version is 3.10 via python -V</p><h3>Step 5: Install dependencies for OpenUI</h3><p>First let’s build the frontend artefacts. In your terminal navigate into the frontend directory with:</p><pre>cd openui/frontend</pre><p>Then run the installation and build.</p><pre>npm install<br>npm run build -- --mode hosted</pre><p>Now navigate to the backend directory (assuming your still in the frontend directory) with:</p><pre>cd ../backend</pre><p>Now install the Python dependencies via:</p><pre>pip install .</pre><h3>Step 6: Adjust port and host</h3><p>Currently OpenUI does not support changing the port via a command line flag or similar so we will need to do a small change to the source code.</p><p>Open the file /openui/backend/openui/__main__.py and change line 55 to:</p><pre>host=&quot;0.0.0.0&quot;,</pre><p>and line 57 to:</p><pre>port=3000,</pre><p>Now save the changes with command+s.</p><h3>Step 7: Download model &amp; run Ollama server</h3><p>Navigate to the root directory via:</p><pre>cd /home/user/app</pre><p>And launch the Ollama server via:</p><pre>./ollama serve&amp;./ollama run llava</pre><p>This will download the model (takes a few seconds) and start a prompt shell, to verify it is actually working type a prompt and see if it will produce output. If it works exit the prompt context via control + d (mac) or strg + c on windows.</p><h3>Step 8: Run the UI builder and enjoy!</h3><p>Make sure your still inside your pipenv and then in the same! terminal now type:</p><pre>cd /home/user/app/openui/backend<br>python -m openui</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/0*huUbTgeGa3pkyveI.gif" /></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=5a5ed852a98a" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Host Your Discord Bot on Codesphere]]></title>
            <link>https://medium.com/codesphere-cloud/host-your-discord-bot-on-codesphere-57873c580a3f?source=rss-86282414923b------2</link>
            <guid isPermaLink="false">https://medium.com/p/57873c580a3f</guid>
            <category><![CDATA[discord-bot]]></category>
            <category><![CDATA[discord]]></category>
            <category><![CDATA[discord-js]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[tutorial]]></category>
            <dc:creator><![CDATA[Codesphere]]></dc:creator>
            <pubDate>Tue, 02 Jan 2024 10:42:26 GMT</pubDate>
            <atom:updated>2024-01-02T10:42:26.358Z</atom:updated>
            <content:encoded><![CDATA[<p>On Codesphere you can effortlessly host your Discord bot. This tutorial demonstrates the process of creating a bot and adding it to your server. It also explains how to set up the workspace with environmental variables and connect a SQLite database. Additionally, it explains how to utilize Discord Developer Mode for this purpose.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*XaZPF1t1W0gL684hUg_eRw.png" /></figure><p>Our ‘Registration Bot’ from our own community server serves as the basis for the bot featured in this tutorial. This bot manage the sign-up process for our monthly challenges.</p><p>The bot prompts users for an email address and optionally a Team ID and team name. After signing up, the bot creates a Team ID and sends it directly to the user, allowing them to invite friends to their team. Also, everyone who is using this Slash command gets a new role on the server. A SQLite database stores all the data.</p><p>With that said, let’s begin recreating this bot. If you are interested in creating your own Discord bot, you can refer to the official tutorials from Discord.js: <a href="https://discordjs.guide/">Discord.js Guide</a></p><h4><strong>Create a discord bot application</strong></h4><p>Log in to your Discord account on the Discord Developer Portal: <a href="https://discord.com/developers/applications">Discord Developer Portal</a></p><p>Create a new application by clicking the blue ‘New Application’ button in the top right corner. Name your bot application and agree to the terms and conditions.</p><p>Congratulations, you now have your first Discord application. Remember, never share any credentials for an application with others to prevent misuse of your bot.</p><h4><strong>Invite the Bot to your server</strong></h4><p>Go to OAuth2 and then to the URL Generator. Here, we will generate the invitation link for our bot. In this section, we can set up all the permissions the bot needs to fulfill its functions.</p><p>The more permissions your bot has, the more ‘power’ it has. However, with great power comes a higher risk of misuse if any secret credentials fall into the wrong hands. Only select the necessary permissions and nothing more. For the use case in our Discord Bot Template, you need the following permissions:</p><p>Now, your bot has joined your server and is visible in the member list on the right.</p><figure><img alt="member list discord" src="https://cdn-images-1.medium.com/proxy/0*lLYpTSvqbqENyf2C" /></figure><p>As you can see, the bot is currently offline. In the next step, we will host our bot in a Codesphere workspace so that it can come online.</p><h4><strong>Set up the Bot on the server</strong></h4><p>Create a new workspace and clone the Git repository. You can run the prepare stage of the CI-Pipeline to install all necessary dependencies.</p><p>Git repo: <a href="https://github.com/codesphere-cloud/TutorialBot">https://github.com/codesphere-cloud/TutorialBot</a></p><h4>Create environmental variables</h4><p>For security reasons, we use environmental variables to load sensitive data into our Bot. This prevents hardcoding sensitive information in the source code. In this section, we’ll set up the required environmental variables in Codesphere.</p><p>Now you need to set up the bot’s token which is essentially the password for the bot.</p><p>You can get your first token in the Discord Developer Portal in the Bot section</p><figure><img alt="get token Discord Bot" src="https://cdn-images-1.medium.com/proxy/0*p6OOqrw7A2HVGHYe" /></figure><p>Create your first token. Keep in mind that you can only view this token once, so make sure to save it securely. However if you lose your token, you can reset it.</p><p>Note: If a token is not valid, your bot can’t go online.</p><p>Now we can set up the environmental variable. For this, go to ‘Set up’ and then select ‘Env var’ in the menu.</p><p>Add a new variable, name the key ‘token’ and paste the token you copied from the Discord Developer Portal into the value field.</p><p>Name the key ‘token’ to enable the Bot’s utilization of it. If you decide to change the variable name, make sure to update the source code in both ‘index.js’ and ‘deploy-commands.js’ within your project.</p><p>In JavaScript, call environmental variables using the command ‘process.env.[…]’.</p><p>Replace […] with the key value of your environmental variable.</p><p>To test if the token is valid, you can start the run stage. Wait for the terminal to display ‘Ready! Logged in as Tutorial#…’ and when your bot is online, it is live!</p><p>To load our new Slash commands onto the Discord server, we need to set up two more environmental variables: userID and serverID. To get these IDs from Discord, we need to enable the Discord Developer mode.</p><p>Go to the account settings and select ‘advanced’. There you can enable the ‘Developer Mode’:</p><p>Now, you can retrieve any ID you want from Discord. We specifically need the serverID and the userID from the bot.</p><p>To get the serverID/userID, right-click the server name/Tutorial Bot, and click on the toggle-down menu to copy the Server ID/ User ID:</p><h4><strong>Create a new role</strong></h4><p>To enable the bot to assign the Slash command user to a new role, we need to set up a role on the server.</p><p>For that we create a new role on the server. Go to the server setting and navigate to ‘Roles’. Here you can easily create a new role:</p><p>You can customize various settings for a role. To keep this tutorial short, I suggest exploring these settings on your own to discover the possibilities. Once you’ve finished setting up your new role, remember to save the changes.</p><p>In Discord, roles have a hierarchy. The bot must have a higher rank than the new role. Without this, the bot won’t have permission to assign this role to any user. To adjust the rank of the roles, click and hold the left mouse button on the eight dots to the left of the roles and drag the role to the desired rank:</p><p>The Bots role must be above the new role (in this picture the Participant role). Save the changes again, and Discord sets up the new role.</p><p>Now we need to copy the roleID and create a new environmental variable called ‘roleID’ so that the bot can add this role to a user who uses the /signup command. Right-click on the role to get the ID:</p><p>Name this new variable ‘roleID’ and assign it the value of the ID you just copied. This lets the bot access and use the role ID when handling the /signup command.</p><h4><strong>Create the SQLite Database</strong></h4><p>To store the email addresses and teams of the participants, we will set up an SQLite Database. In this section, we will learn how to use the SQLite UI in Codesphere.</p><p>Go to setup in your workspace and select Database in the menu and create a new Database. Name your Database ‘Member’, so that you don’t need to change the source code.</p><p>Note: If you decide to change your database’s name, make sure to update the source code wherever it mentions the database. For example, you may need to modify the code in ‘events/modal.js’::</p><figure><img alt="hardcoded Database" src="https://cdn-images-1.medium.com/proxy/0*c_bL_IY3T36b1sQN" /></figure><p>Then, we want to create tables to insert and save the data.</p><p>Go to the Setup menu and click on SQLite. Right click on your database Member and select open Query editor:</p><p>To create these tables in your database, copy the following two codes and paste each in a separate query tab. You need to create the ‘team’ table before the ‘participant’ table’:</p><p>a) team:</p><pre>CREATE TABLE team (<br>      teamid INTEGER PRIMARY KEY AUTOINCREMENT,<br>      teamname TEXT UNIQUE,<br>      verificationcode TEXT UNIQUE<br>  );</pre><p>b) participant:</p><pre>CREATE TABLE participant (<br>      userid INTEGER PRIMARY KEY,<br>      username TEXT,<br>      email TEXT,<br>      teamid INTEGER NOT NULL,<br>      FOREIGN KEY (teamid) REFERENCES team(teamid)<br>);</pre><p>Now you should see in the menu that two tables exists:</p><h4><strong>Ready to Use</strong></h4><p>With everything set up, restart the run stage, and the bot will come online, allowing you to use the /signup command on your server.</p><p>You can query the database to see who signed up. For that go to the query editor like before and open a new query tab. You can simply insert this SQL code that queries all participants and their assigned team:</p><pre>SELECT participant.userid, <br>        participant.username, <br>        participant.email, <br>        team.teamname <br>FROM   participant <br>INNER JOIN team ON participant.teamid = team.teamid;</pre><p>Ready to create your own bot with discord.js? This tutorial just scratched the surface — there are so many more possibilities!</p><h4>Discord Community Server</h4><p>Keen on connecting with fellow Discord Bot creators? Join our Discord Codesphere Community Server:</p><p><a href="https://discord.gg/codesphere">Codesphere Community Server</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=57873c580a3f" width="1" height="1" alt=""><hr><p><a href="https://medium.com/codesphere-cloud/host-your-discord-bot-on-codesphere-57873c580a3f">Host Your Discord Bot on Codesphere</a> was originally published in <a href="https://medium.com/codesphere-cloud">Codesphere</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Digitizing Processes Made Easy: LLM + Low Code Workflow on Codesphere]]></title>
            <link>https://medium.com/codesphere-cloud/digitizing-processes-made-easy-llm-low-code-workflow-on-codesphere-a4c9a1c6404f?source=rss-86282414923b------2</link>
            <guid isPermaLink="false">https://medium.com/p/a4c9a1c6404f</guid>
            <category><![CDATA[low-code-automation]]></category>
            <category><![CDATA[self-hosted]]></category>
            <category><![CDATA[tutorial]]></category>
            <category><![CDATA[hugging-face]]></category>
            <category><![CDATA[large-language-models]]></category>
            <dc:creator><![CDATA[Codesphere]]></dc:creator>
            <pubDate>Tue, 02 Jan 2024 10:36:25 GMT</pubDate>
            <atom:updated>2024-01-02T10:36:25.381Z</atom:updated>
            <content:encoded><![CDATA[<p>Automating tasks with a Large Language Model on Codesphere is straightforward, even for those with minimal coding experience. You can save on development time and costs by utilizing low-code automation tools like n8n, which can be self-hosted on Codesphere.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/1*rwlh2k5fqP42Yj3GieZ_jw.jpeg" /></figure><p>To demonstrate low-code automation on Codesphere, we’ll create a News Bot. This bot will post a weekly summary of the top 10 trending AI models from Hugging Face on a Discord server. We’ll achieve this by utilizing the Hugging Face API to fetch the trending models and employing a self-hosted Large Language Model (LLM) for summarization.</p><h4>Prerequisites</h4><p>For this task, we’ll together set up an n8n instance, a self-hosted Llama.cpp instance, and a basic Flask app. You need to create 3 workspaces in total:</p><ul><li>Codesphere Account: <a href="https://signup.codesphere.com/">Sign up</a></li><li>n8n instance: <a href="https://codesphere.com/articles/n8n-a-cost-saving-zapier-alternative-hosted-on-codesphere-2#heading-0">n8n Tutorial</a></li><li>workspace with the Flask app (Free plan): <a href="https://github.com/codesphere-cloud/flask-app-HuggingFace">Git-Hub link</a></li><li>llama.cpp-python endpoint workspace: <a href="https://github.com/codesphere-cloud/llama2-endpoint">llama2 + API template</a> + <a href="https://www.youtube.com/watch?v=bPOEqqhJ05g">YT-Tutorial</a></li></ul><h4>n8n workflow</h4><p>You can locate a copy of the workflow in our GitHub repository, available in the n8n starting guide: [<a href="https://codesphere.com/articles/n8n-a-cost-saving-zapier-alternative-hosted-on-codesphere-2#heading-0">n8n Tutorial</a>]. If you already have an n8n instance on Codesphere, simply pull the repository. If you don’t have an n8n instance yet, create a new workspace using this GitHub link.</p><p><a href="https://github.com/codesphere-cloud/n8n-Template">GitHub - codesphere-cloud/n8n-Template: This is the n8n Template for hosting n8n in Codesphere. It is used in the Blog articl &#39;n8n - a Cost-Saving Zapier Alternative Hosted on Codesphere&#39;</a></p><p>GitHub link for creating a n8n instance</p><p>Next, download the HuggingFace.json workflow file to later import it into your own workflows. You can find instructions on how to do this <a href="https://codesphere.com/articles/n8n-a-cost-saving-zapier-alternative-hosted-on-codesphere-2#heading-1">here</a>. The provided workflow corresponds to the one discussed in this article:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*_3EekAdR5V1WGP7-.png" /><figcaption>Workflow</figcaption></figure><p>Next, we’ll set up the workflow together.</p><h4>Discord Webhook</h4><p>To post the summary of the model cards on one of our Discord servers, create a new Discord Webhook and paste the generated Webhook URL into the corresponding fields. Instructions on generating a new Webhook can be found <a href="https://codesphere.com/articles/n8n-a-cost-saving-zapier-alternative-hosted-on-codesphere-2#heading-3">here</a>.</p><p>Insert the Webhook URL into the two Discord nodes on n8n to enable the posting of messages on Discord.</p><h4>Flask app</h4><p>Flask is a lightweight and web framework written in Python. It is designed to be simple and easy to use, making it a popular choice for building web applications and APIs (Application Programming Interfaces) in Python.</p><p>In this workflow we use a Flask app to scrape the model cards of the top 10 trending AI models on Hugging Face when accessing the API endpoints: <a href="https://huggingface.co/models">trending models</a>.</p><p>For this Flask template you can use a free plan. Just create a new workspace using this GitHub link:</p><p><a href="https://github.com/codesphere-cloud/flask-app-HuggingFace">GitHub - codesphere-cloud/flask-app-HuggingFace: This is the simple Flask app for the Tutorial: &quot;Building a Hugging Face Newsbot on Top of a Self-Hosted Open-Source LLM&quot;</a></p><p>GitHub link for the Flask app.</p><p>Here you can see how to create a new workspace and clone a Git-Hub repository in one simple step on Codesphere:</p><p>When you created a workspace which contains this Flask project, the only thing you need to do is to hit the ‘prepare’ and ‘run’-stage of the CI-pipeline.</p><p>Afterwards we need to set up the HTTP-request nodes on n8n which utilizes the API of this Flask app. For that you need to copy your workspace-URL of the Flask app and paste it in the URL field.</p><p>In the get model namenode you need to append /get_trending_modelsto that URL.</p><p>In the Get Model Descriptionnode, append /get_model_card to the URL. Additionally, set up a query string in the URL that contains information about the model you want to access. Now, append ?model_name= to the URL.</p><p>Lastly, drag and drop the model name, which we scraped in a previous node, into our query string. This will serve as a placeholder for every model we scraped, and this query will be performed for every set of 10 models:</p><p>In the Flask app, we’ve limited the maximum number of scraped words to 200. Adjust the word count by modifying the value in line 80:</p><p>model_card_content_first_200_words = &#39; &#39;.join(words[:200])</p><p>Line 80 in app.py</p><h4>Llama.cpp Python API</h4><p>For the LLama.cpp instance, we recommend using either a Pro plan or a shared-GPU plan to ensure optimal performance for the Large Language Model (LLM). Simply use the Llama2 + API template provided in the create workspace interface.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/711/0*tnhirH7dL5nW2cew.png" /><figcaption>The pointer shows which Template you can use</figcaption></figure><p>When starting the prepare-stage of the CI-Pipeline, it takes a few minutes to download the entire model to our workspace. In this workflow, we are using the SlimOrca-13B-GGUF model in the GGUF format:</p><p><a href="https://huggingface.co/TheBloke/SlimOrca-13B-GGUF">TheBloke/SlimOrca-13B-GGUF · Hugging Face</a></p><p><a href="https://huggingface.co/TheBloke/SlimOrca-13B-GGUF">We’re on a journey to advance and democratize artificial intelligence through open source and open science.</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*0dTyMoocEEfPDe_A.png" /></figure><p>Feel free to select different models, and we suggest using the GGUF format for the best results.</p><p>To configure the HTTP request to our self-hosted LLM in the n8n workflow, simply copy and paste the workspace URL form the llama.cpp instance into the summarize node. Then, append /v1/completion to the URL. Since this HTTP request needs to be a POST method, include a JSON request body representing the prompt for the summarization task.</p><pre>{   &quot;prompt&quot;: &quot;\n\n# Instructions:\nplease provide a bullet point summary. Print before every bullet point a new line but as escaped character. Furthermore just provide up to 3 bullet points. each bullet point must start with *. This is the structure for your output: ## Modeltype\n*(bulletpoints)\n## Summary\n*(bulletpoints)\n\nin the following section is the text to analyse:\n{{ $json.text }}\n\n# Response: in the following i will summarize the model card of the  model {{ $json.name }}:\n&quot;,   &quot;stop&quot;: [ &quot;\n##Evaluation&quot;, &quot;\n##Model Details&quot;, &quot;\n##Applications&quot;, &quot;\n##OutofScope Use Restrictions&quot;, &quot;\n##Research Applications&quot;, &quot;\n##license&quot;, &quot;\n##model sources&quot;, &quot;\n##User Study&quot;, &quot;\n##excluded uses&quot;, &quot;\n###Links&quot;, &quot;\n###Usage&quot;   ] }</pre><p>You can customize many aspects in the prompt. Click ‘Open Deployment’ in the top right corner of the llama.cpp workspace and add /docs to the URL for API documentation, where you&#39;ll find details on prompt configuration.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*ZpHUIWBOcPInRcRR.png" /><figcaption>API documentaion for this llama.cpp instance</figcaption></figure><p>We utilized the prompt section to define the prompt’s context. While you can stick with the default prompt in this workflow template, we encourage you to experiment and customize it as needed.</p><h4>Result</h4><p>With everything set up, you can now activate your workflow. The workflow is scheduled to trigger every week at 8 am. If needed, you can adjust this schedule in the node:</p><p>When triggered, this workflow initiates two HTTP requests to our Flask app, overseeing the scraping of AI model cards through the official HuggingFace API. During the data scraping process, we preprocess the text by removing unnecessary stopwords. This step is taken to eliminate redundant information that adds no value to the context and only occupies unnecessary space.</p><p>After collecting this data, we can now feed the preprocessed text into our LLM using our prompt. The workflow loop iterates through all 10 AI models, resulting in a summary for each model. This loop can take a couple of minutes, depending on the size of the prompt.</p><p>Finally, we send these results to our Discord Webhook as embeds, ensuring that the summary of each AI model is posted in a dedicated channel within our Discord server:</p><p>This workflow serves as a demonstration of the possibilities achievable through low-code solutions on Codesphere. By seamlessly integrating various tools and technologies, we’ve showcased how you can automate complex tasks efficiently.</p><p>Explore the potential of these tools, experiment, and simplify the development process with Codesphere.</p><h4>Discord Community Server</h4><p>If you want to connect with fellow Codesphere users and developers you can join our Discord Community Server: <a href="https://discord.gg/codesphere">https://discord.gg/codesphere</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a4c9a1c6404f" width="1" height="1" alt=""><hr><p><a href="https://medium.com/codesphere-cloud/digitizing-processes-made-easy-llm-low-code-workflow-on-codesphere-a4c9a1c6404f">Digitizing Processes Made Easy: LLM + Low Code Workflow on Codesphere</a> was originally published in <a href="https://medium.com/codesphere-cloud">Codesphere</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Building an AI powered search in Node.js using Qdrant Cloud]]></title>
            <link>https://medium.com/codesphere-cloud/building-an-ai-powered-search-in-node-js-using-qdrant-cloud-96e6d6c4c851?source=rss-86282414923b------2</link>
            <guid isPermaLink="false">https://medium.com/p/96e6d6c4c851</guid>
            <category><![CDATA[codesphere]]></category>
            <category><![CDATA[nodejs]]></category>
            <category><![CDATA[qdrant]]></category>
            <category><![CDATA[tutorial]]></category>
            <dc:creator><![CDATA[Codesphere]]></dc:creator>
            <pubDate>Tue, 02 Jan 2024 10:33:03 GMT</pubDate>
            <atom:updated>2024-01-02T10:33:03.274Z</atom:updated>
            <content:encoded><![CDATA[<p>Since the launch of ChatGPT, we’ve been seeing more and more use cases for LLMs reaching from helping with ideation to complex support agents connected to custom data bases.</p><p>In this article, I will talk about how I set up an AI powered search in Node.js. This can be used for any use case. In my case i connected it to the Codesphere blog, enabling an AI powered search.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/1*Tcr-FKUAiO6AgTnjLilUHA.jpeg" /></figure><h4>What is Qdrant</h4><p>In a nutshell, Qdrant provides vector databases, featuring a user-friendly API for managing collections of data points, querying, and searching.</p><p>My experience with vector databases began with Qdrant, which simplified an otherwise complex environment. It offers a JavaScript SDK, integrating seamlessly with existing Node.js projects to leverage the capabilities of large language models (LLMs).</p><p>All of this is tied together through Qdrant Cloud which essentially provides managed Qdrant databases for you to use and includes a free tier. It has a convenient graphical interface which can be used to look at the collections created.</p><h4>Understanding Vector Databases</h4><p>In more sophisticated applications involving large language models (LLMs) in some way, vector databases are often used to handle custom data. Unlike traditional databases that store data in tables and rows, vector databases use embeddings. These embeddings are lists of numbers representing data in a high-dimensional space, much more complex than a simple three-dimensional space.</p><p>The transformation of regular data into vector embeddings is carried out by trained LLMs. These models understand the context and semantics of the data, converting it into a vector that accurately represents its meaning in this multi-dimensional space. This allows for efficient processing and comparison of complex data, such as text or images, enabling more sophisticated and context-aware search capabilities.</p><h4>The Workflow for my Blog Search</h4><p>Having understood the basics about how a vector database works and how data can be converted into embeddings, the workflow itself is pretty simple:</p><ol><li>Create a collection</li><li>Check which articles are already in the Qdrant database</li><li>Create embeddings for missing articles</li><li>Upload to Qdrant</li></ol><p>With that, it is possible to create embeddings for search queries and search the collection in the database.</p><h4>Setting Up Qdrant in JavaScript</h4><p>Before diving into the specifics of building the AI-powered search, it’s crucial to understand how to set up Qdrant in a JavaScript (Node.js) environment. This setup forms the foundation upon which all the subsequent functionalities rely.</p><h4>Qdrant Client Initialization</h4><p>First, you’ll need to initialize the Qdrant client. This client acts as the bridge between your Node.js application and the Qdrant database, enabling you to interact with the database programmatically.</p><pre>import { QdrantClient } from &quot;@qdrant/js-client-rest&quot;;<br><br>const client = new QdrantClient({ <br>    url: &#39;https://[your-qdrant-instance-url]&#39;,<br>    apiKey: &quot;[your-api-key]&quot;<br>});</pre><p>Replace &#39;[your-qdrant-instance-url]&#39; and &#39;[your-api-key]&#39; with your Qdrant instance URL and API key. This setup assumes you have an account with Qdrant Cloud and have set up a database instance.</p><p>One thing to note is, that at least for me, I couldn’t get the SDK to work with a local in memory setup of the database without using Docker. So keep in mind that you will either need Qdrant Cloud or a custom Docker image running locally with your database in it. Running a managed Docker image on Digital Ocean unfortunately didn’t work for me either.</p><h4>Installing Required Libraries</h4><p>To fully leverage the capabilities of Qdrant and LLMs, you’ll need to install certain libraries. The @qdrant/js-client-rest library is used for interacting with the Qdrant API, and @xenova/transformers for processing text into vector embeddings.</p><pre>npm install @qdrant/js-client-rest @xenova/transformers</pre><p>This command installs the necessary Node.js packages into your project, allowing you to use the Qdrant client and the Xenova pipeline for text encoding.</p><h4>Text Encoding with Xenova</h4><p>The Xenova pipeline is a crucial part of transforming text data into vector embeddings. This is done through the encodeText function, which leverages a pre-trained model to process text.</p><pre>import { pipeline } from &quot;@xenova/transformers&quot;;<br><br>async function encodeText(text) {<br>    const extractor = await pipeline(&quot;feature-extraction&quot;, &quot;Xenova/all-MiniLM-L6-v2&quot;);<br>    return await extractor(text, {pooling: &quot;mean&quot;, normalize: true});<br>}</pre><p>With these initial setup steps, you’re now ready to dive into creating and managing your AI-powered search functionality using Qdrant.</p><p>Following this setup guide, let’s delve into the four key steps of building the AI-powered search.</p><h4>1. Creating a Collection with Qdrant</h4><p>To kickstart the AI-powered search, the first task is setting up a collection in the Qdrant database. Think of a collection as a flexible and dynamic container for your data, specifically tailored for vector-based operations.</p><h4>Function: recreateQdrantCollection</h4><p>The recreateQdrantCollection function is our gateway to initializing this collection. It&#39;s here that we define the crucial parameters of our vector space, like its size and the distance metric, which are key to how our data will be interpreted and queried. The vector size will be determined by the LLM you&#39;re using for transforming your data into embeddings. I simply just ran an example conversion to get the right size.</p><pre>async function recreateQdrantCollection(collectionName, vectorSize) {<br>    console.log(&quot;Creating collection&quot;);<br>    try {<br>        await client.recreateCollection(collectionName, {<br>            vectors: {<br>                size: vectorSize,<br>                distance: &quot;Dot&quot;<br>            }<br>        });<br>        console.log(`Collection ${collectionName} created successfully`);<br>    } catch (error) {<br>        console.error(`Error creating collection ${collectionName}:`, error);<br>        throw error;<br>    }<br>}</pre><p>As soon as the collection has been created, you will be able to see, access and manage it from the Qdrant dashboard:</p><h4>2. Checking Existing Articles in the Database</h4><p>Once the collection is set, it’s important to ensure we’re only adding new or updated content. This step is crucial for maintaining efficiency and avoiding redundancy.</p><h4>Function: scrollThroughPoints</h4><p>The scrollThroughPoints function comes into play here. It retrieves the IDs of all articles currently stored in the collection, giving us a clear picture of what’s already in there.</p><pre>async function scrollThroughPoints(collectionName) {<br>    let existingIds = [];<br>    try {<br>        let hasMore = true;<br>        let scrollId = null;<br><br>        while (hasMore) {<br>            const response = await client.scroll(collectionName, {<br>                limit: 1000,<br>                with_payload: false,<br>                with_vector: false,<br>                scroll_id: scrollId,<br>            });<br><br>            response.points.forEach(point =&gt; existingIds.push(point.id));<br>            scrollId = response.scroll_id;<br>            hasMore = response.points.length &gt; 0;<br>        }<br>    } catch (error) {<br>        console.error(`Error scrolling through points in collection &#39;${collectionName}&#39;:`, error);<br>    }<br><br>    return existingIds;<br>}</pre><p>Keep in mind that there is a limit to set here which you should take a look at before running it. You can then use the data retreived from the database to check if your articles are already in the collection or not by comparing the ids.</p><h4>3. Creating Embeddings for Missing Articles</h4><p>For the articles that are not in the collection, we need to transform their textual content into a format that Qdrant can understand and work with — vector embeddings.</p><h4>Function: encodeText</h4><p>Here’s where encodeText shines. It uses an LLM to convert text into vector embeddings, encapsulating the nuances and context of the content into a numerical form.</p><pre>async function encodeText(text) {<br>    const extractor = await pipeline(&quot;feature-extraction&quot;, &quot;Xenova/all-MiniLM-L6-v2&quot;);<br>    return await extractor(text, {pooling: &quot;mean&quot;, normalize: true});<br>}</pre><h4>4. Uploading to Qdrant</h4><p>The final step in the setup is populating our Qdrant collection with these freshly minted embeddings.</p><h4>Function: uploadDocuments</h4><p>The uploadDocuments function takes these embeddings and carefully places them into our collection, making sure each piece of content is correctly represented and stored.</p><pre>async function uploadDocuments(collectionName, documents) {<br>    console.log(&quot;Uploading documents&quot;);<br>    const points = documents.map(doc =&gt; ({<br>        id: doc.id,<br>        vector: doc.vector,<br>        payload: doc.payload<br>    }));<br><br>    try {<br>        await client.upsert(collectionName, { points });<br>        console.log(`Documents uploaded successfully to collection &#39;${collectionName}&#39;`);<br>    } catch (error) {<br>        console.error(`Error uploading documents to collection &#39;${collectionName}&#39;:`, error);<br>    }<br>}</pre><p>Keep in mind, that Qdrant does not support any kind of ids. The official documentation states that Qdrant supports using both 64-bit unsigned integers and UUID as identifiers for points.</p><p>In my case this was perfect, as our blog CMS (Ghost.io) provides a UUID for each article which I could just use to identify my points.</p><h4>Implementing AI-Powered Search</h4><p>After setting up our collection and populating it with blog articles, the next crucial step is to implement the search functionality. This involves querying the Qdrant database with a search vector and retrieving the most relevant articles.</p><h4>Function: searchArticles</h4><p>The searchArticles function is designed to perform this task. It takes a search query, converts it into a vector embedding (similar to how we processed our blog articles), and then uses this vector to search our Qdrant collection for the most relevant matches.</p><p>Here’s an example of how this function could be structured:</p><pre>async function searchArticles(query) {<br>    const vector = await encodeText(query); // Convert query text to vector<br><br>    try {<br>        const searchResults = await client.search(&quot;codesphere_blog&quot;, {<br>            params: {<br>                hnsw_ef: 128,<br>                exact: false,<br>            },<br>            vector: vector,<br>            limit: 3, // Adjust limit as needed<br>        });<br><br>        console.log(&quot;Search results:&quot;, searchResults);<br>        // Further processing of searchResults as needed<br>    } catch (error) {<br>        console.error(&quot;Error during search:&quot;, error);<br>    }<br>}<br><br>// Example usage of searchArticles<br>searchArticles(&quot;AI powered search&quot;).catch(console.error);</pre><p>In this function, encodeText is used again to convert the search query into a vector. This vector is then passed to the client.search method, along with the name of your collection and other search parameters. The limit parameter determines how many results to return, and the hnsw_ef parameter is a configuration for the search algorithm (feel free to adjust these values based on your requirements).</p><p>With this setup, you can perform searches against your Qdrant collection, harnessing the power of vector similarity to find the most relevant articles for any given query.</p><p>The only thing that is left now is to put all of those pieces together in our production setup and connect it to the frontend. Since we’re currently working on a more sophisticated version, I won’t be going into detail on this but I think this should already give you a good overview about how you can use Qdrant to set up an AI powered search for your blog.</p><h4>Conclusion</h4><p>Qdrant made it very easy for me to get started in the vector database world. The JS SDK includes all necessary methods to interact with the database.</p><p>This in turn made is very easy to incorporate an AI-powered search into our blog. Now this could also be implemented into any other web application for wildly different use cases.</p><p>Whether for a blog, a knowledge base, or any other content-rich platform, this approach opens up new horizons in information retrieval and user engagement.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=96e6d6c4c851" width="1" height="1" alt=""><hr><p><a href="https://medium.com/codesphere-cloud/building-an-ai-powered-search-in-node-js-using-qdrant-cloud-96e6d6c4c851">Building an AI powered search in Node.js using Qdrant Cloud</a> was originally published in <a href="https://medium.com/codesphere-cloud">Codesphere</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Cloud Deployments & Live Code Sync from Visual Studio Code]]></title>
            <link>https://medium.com/codesphere-cloud/cloud-deployments-live-code-sync-from-visual-studio-code-30e502e72241?source=rss-86282414923b------2</link>
            <guid isPermaLink="false">https://medium.com/p/30e502e72241</guid>
            <category><![CDATA[tutorial]]></category>
            <category><![CDATA[codesphere]]></category>
            <category><![CDATA[cloud]]></category>
            <category><![CDATA[sync]]></category>
            <category><![CDATA[vscode]]></category>
            <dc:creator><![CDATA[Codesphere]]></dc:creator>
            <pubDate>Tue, 02 Jan 2024 10:24:33 GMT</pubDate>
            <atom:updated>2024-01-02T10:24:33.660Z</atom:updated>
            <content:encoded><![CDATA[<p>Codesphere has its own cloud based code editor. It is optimized for speed and works as a simple collaborative text editor for coding. While we are constantly expanding its functionality it is of course not as powerful as the leading local IDEs out there. However in this blog post we are going to show you a way to connect your local Visual Studio Code (or the browser version thereof) to any Codesphere workspace in 5 minutes.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*PEjhANPVPLumgclBcD7AFw.png" /></figure><p>Picture this: using your local Visual Studio Code to seamlessly sync with Codesphere Workspaces bidirectionally, giving you the full power of Visual Studio Code and the deployment &amp; compute in Codesphere. You can leverage the full compute power of your workspace even for local development. The days where local development requires expensive hardware will soon be in the past, what we are showing today works on any device, as long as you have internet access and a modern browser. It even works from an iPad or your phone.</p><p>You can fully utilise the collaborative possibilities, co-create with other developers or share sessions with project managers and other stakeholders. ‘Works on my machine’ is no longer a valid excuse. Ready to dive in?</p><h4>How to set it up (takes 5 min or less)</h4><ol><li>Open any existing Codesphere workspace</li><li>Open a terminal and enter the following commands</li></ol><pre>curl -Lk &#39;https://code.visualstudio.com/sha/download?build=stable&amp;os=cli-alpine-x64&#39; --output vscode_cli.tar.gz<br>tar -xf vscode_cli.tar.gz<br>./code tunnel</pre><ol><li>Follow the instructions in the terminal, you can login via GitHub or a Microsoft account</li><li>We select GitHub and navigate to <a href="https://github.com/login/device">https://github.com/login/device</a>, enter the code provided in the terminal and submit</li><li>Back in the terminal, provide a name for this tunnel and open the link provided in any browser <a href="https://vscode.dev/tunnel/&lt;machine_name&gt;/">https://vscode.dev/tunnel/&lt;machine_name&gt;/&lt;folder_name&gt;</a></li><li>Alternatively you can open your local VS Code, install the Remote - Tunnels extension from Microsoft and follow the instructions to connect your tunnel</li></ol><p>And that’s it. If you now open a terminal in your Visual Studio instance you can run all commands like you would in Codesphere. Files changed either on Codesphere or in VS Code are bidirectionally synced in almost real-time.</p><figure><img alt="Live demo, Codesphere x Visual Studio Code" src="https://cdn-images-1.medium.com/max/800/0*IP-OOqe5P_f2L8x1.gif" /></figure><h4>Why is that amazing?</h4><ul><li>Access to higher performance e.g. GPU’s from a limited machine</li><li>Share it with PMs, Stakeholders, and Tech Leads immediately (it’s live and deployed)</li><li>Access the whole landscape from your laptop (e.g. test databases, other services)</li><li>Use your local extensions to modify a preview deployment</li><li>Use this in meetings as a replacement for screen sharing, both can edit live, run, and test the code</li><li>‘Works on my machine’ is a thing of the past</li><li>No code needs to be stored on your laptop -&gt; more secure</li><li>No more installing of the development environment, it is already set up and is the same as previews, staging, and production</li><li>Just connect to any deployment from GitHub and fix it if it did not work 😄</li></ul><p>This is also different to other CDE platforms like Codesandbox and Gitpod, because Codesphere covers the whole software lifecycle from preview to production, with CI Pipelines, Replicas, Autoscaling, Microservice Support, Managed Services, GPU’s, etc.</p><p><a href="https://signup.codesphere.com/?utm_source=blogSnippet&amp;utm_campaign=blog">Sign Up Today!</a></p><p>Happy coding 💜</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=30e502e72241" width="1" height="1" alt=""><hr><p><a href="https://medium.com/codesphere-cloud/cloud-deployments-live-code-sync-from-visual-studio-code-30e502e72241">Cloud Deployments &amp; Live Code Sync from Visual Studio Code</a> was originally published in <a href="https://medium.com/codesphere-cloud">Codesphere</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[n8n — a Cost-Saving Zapier Alternative Hosted on Codesphere]]></title>
            <link>https://medium.com/codesphere-cloud/n8n-a-cost-saving-zapier-alternative-hosted-on-codesphere-619c62c6f903?source=rss-86282414923b------2</link>
            <guid isPermaLink="false">https://medium.com/p/619c62c6f903</guid>
            <category><![CDATA[n8n]]></category>
            <category><![CDATA[workflow]]></category>
            <category><![CDATA[zapier]]></category>
            <category><![CDATA[n8n-workflow]]></category>
            <category><![CDATA[self-hosted]]></category>
            <dc:creator><![CDATA[Codesphere]]></dc:creator>
            <pubDate>Tue, 05 Dec 2023 09:59:20 GMT</pubDate>
            <atom:updated>2023-12-05T09:59:20.929Z</atom:updated>
            <content:encoded><![CDATA[<h3>n8n — Save money with this self hosted Zapier alternative</h3><p>In the world of automating tasks, Zapier has been a go-to for many. But here’s the thing — if you’re looking for more control and a wallet-friendly option, consider n8n the open-source workflow automation tool.</p><p>The cool thing is that you can host it yourself, and if you do it on Codesphere, you’ll save money compared to use Zapier. Plus, you get full control over your data and how your workflows play out.</p><p>In this article, we’re going to show you just how simple it is to set up your own n8n instance on Codesphere. We will guide you through the process of getting started effortlessly. Let’s make the most of n8n’s potential with the ease of self hosting on Codesphere — it’s a win-win.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/1*QSn1NrYJPjGQy98TNPklig.jpeg" /></figure><h4>set up the n8n workspace</h4><p>Let’s get your n8n workspace up and running on Codesphere. You just need to follow these steps:</p><ul><li>Choose Your Plan:</li></ul><p>Pick either “Always On” or “Off When Unused” for your workspace. If you choose “Off When Unused,” remember it shuts down after an hour of inactivity. Don’t worry, though — your workspace will reboot the next time you use it, although it might take a bit.</p><ul><li>Add this GitHub Repository:</li></ul><p>link: <a href="https://github.com/codesphere-cloud/n8n-Template">https://github.com/codesphere-cloud/n8n-Template</a></p><ul><li>Run “Prepare” and “Run” stages in the CI-Pipeline:</li><li>Open Deployment and Set Up the user account for this n8n instance</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/0*yNbRqNK3ktfWcO4f.gif" /><figcaption>Create a workspace for hosting n8n on Codesphere</figcaption></figure><p>Your n8n workspace is set! Now, dive in and start creating your workflows. The n8n interface is user-friendly, making it easy to build workflows tailored to your tasks.</p><p>Next up, we’ll guide you through setting up the workflow integrations: Discord, Todoist and Rowbase.</p><h4>Loading the predefined workflow</h4><p>Now that your n8n workspace is up and running on Codesphere, let’s dive into effortlessly loading a predefined workflow. Follow these simple steps:</p><ul><li>Download the Workflow JSON:</li></ul><p>In the Codesphere IDE, right-click on the provided JSON file for the predefined workflow. Select “Download” to save it directly to your device.</p><ul><li>Import the Workflow:</li></ul><p>Inside your n8n workspace, navigate to the workflows section. Look for the “Import” option and upload the downloaded JSON file. This action will seamlessly import the predefined workflow into your n8n instance.</p><ul><li>Save Changes</li></ul><figure><img alt="import n8n workflow" src="https://cdn-images-1.medium.com/max/800/0*t-LGUdLCJsXuno1T.gif" /><figcaption>Import the predefined workflow into n8n</figcaption></figure><p>Next up, we’ll guide you through creating a workflow. This one uses RSS feeds to share the latest news on Discord, organizes article data in a table, and sets up a task in a to-do list. This workflow is a hands-on example to demonstrate n8n’s flexibility and power.</p><h4><strong>Prerequisites</strong></h4><p>Once you’ve completed setting up the n8n instance on Codesphere, ensure you have these accounts ready before diving into the showcase workflow:</p><p>Prerequisites for the Showcase:</p><ol><li><a href="https://baserow.io/">Baserow Account</a>: Create an account on Baserow and create a new database.</li><li><a href="https://todoist.com/">Todoist Account</a>: Make sure you have a Todoist account, as it’s part of our workflow.</li><li><a href="https://discord.com">Discord Account</a>: If you don’t have one yet, sign up for a Discord account and create a new server</li></ol><p>Let’s get started with setting up the workflow integrations and see what n8n has to offer!</p><h4>Setting Up Workflow Integrations: Discord</h4><p>Navigate to your Discord server settings and select “Integrations” from the menu. Create a new webhook and copy its URL. Paste this URL into the n8n webhook URL field. In the n8n content field, you can define the message the webhook should generate based on the RSS-feed data.</p><h4>Setting Up Workflow Integrations: Todoist</h4><p>In the n8n UI, create a new credential for Todoist. Copy the API token from Todoist’s settings in the “Integrations” tap and select “Developers” to obtain the API token. Paste the API token into the password field of the n8n credential.</p><h4>Setting Up Workflow Integrations: Rowbase</h4><p>For this integration, you need to set up a Rowbase credential. Simply click on ‘Create New Credential,’ and enter the email address associated with your Rowbase account in the username field, along with your Rowbase account password in the respective fields.</p><p>Once this step is completed, proceed to configure the additional required fields in the Rowbase node to populate the data in the desired table. To achieve this, you’ll need to extract the Database ID from the API Documentation of your Rowbase Database. Copy and paste the Database ID into n8n.</p><p>To load the database into the node, exit the node menu and re-enter it. Now you can choose the table where you want to input the data. Once again, exit the node menu and re-enter it to select the specific columns for your article data.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/0*wc8rtSyDpD-SU_YJ.gif" /><figcaption>Setting up Rowbase integration</figcaption></figure><p>Once completing these steps, you can save your workflow and activate it. This ensures seamless communication between n8n, Discord, Todoist, and Rowbase, allowing you to automate tasks effortlessly.</p><h4>Adding a Custom RSS-Feed Trigger</h4><p>To integrate any RSS feed of your choice into the workflow, follow these steps to create a new RSS-feed trigger:</p><ul><li>Create a New RSS-Feed Trigger:</li></ul><p>Within the n8n workspace, add a new RSS-feed trigger node to your workflow.</p><ul><li>Copy RSS-Feed URL:</li></ul><p>Obtain the URL of the desired RSS feed that you want to integrate.</p><ul><li>Configure the RSS-Feed Trigger:</li></ul><p>Paste the copied RSS-feed URL into the URL field of the RSS-feed trigger node. This ensures that the trigger is connected to the specific RSS feed you want to monitor.</p><ul><li>Connect Trigger to Workflow Nodes:</li></ul><p>Link the RSS-feed trigger to each subsequent node in your workflow. This connection ensures that the workflow responds to updates from the specified RSS feed.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/0*Oog3f4xLSD6Nf005.gif" /><figcaption>Create a new RSS-Feed trigger for any RSS-Feed you desire</figcaption></figure><p>Link: <a href="https://rss.feedspot.com/it_rss_feeds/">Top 100 RSS-Feeds about IT</a></p><h4>Conclusion</h4><p>With these simple steps, you’ve now extended the flexibility of your workflow to incorporate updates from any RSS feed of your choice. The dynamic nature of n8n allows you to adapt and customize your automation seamlessly. Your workflow is now ready to efficiently process and act upon the latest information from the “subscribed” RSS feed.</p><p>With n8n’s incredible flexibility, the options for automation are limitless. This powerful tool offers a variety of features, leaving a wide array of automation possibilities ready for you to explore.</p><p>Are you interested to learn more about Codesphere and n8n? Connect with fellow Codesphere users and reach out to our support team by joining our Discord server!</p><p><a href="https://codesphere.com/discord">Join the Codesphere Community Server on Discord</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=619c62c6f903" width="1" height="1" alt=""><hr><p><a href="https://medium.com/codesphere-cloud/n8n-a-cost-saving-zapier-alternative-hosted-on-codesphere-619c62c6f903">n8n — a Cost-Saving Zapier Alternative Hosted on Codesphere</a> was originally published in <a href="https://medium.com/codesphere-cloud">Codesphere</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Building a beginner-friendly C# application]]></title>
            <link>https://medium.com/codesphere-cloud/building-a-beginner-friendly-c-application-34f298ab3816?source=rss-86282414923b------2</link>
            <guid isPermaLink="false">https://medium.com/p/34f298ab3816</guid>
            <category><![CDATA[tutorial]]></category>
            <category><![CDATA[web-apps]]></category>
            <dc:creator><![CDATA[Codesphere]]></dc:creator>
            <pubDate>Tue, 05 Dec 2023 09:57:14 GMT</pubDate>
            <atom:updated>2023-12-05T09:57:14.491Z</atom:updated>
            <content:encoded><![CDATA[<h3>Building &amp; hosting a beginner-friendly C# application</h3><p>C# was developed by Microsoft and released in the early 2000s as part of the company’s .NET initiative. It was designed with a focus on simplicity, type safety, and object-oriented principles. Since then, it has become a popular language used mainly to develop Windows and web applications using ASP.NET. I wanted to show you how easy it is to run a C# application on <a href="https://codesphere.com/">Codesphere</a>. In this tutorial, I will walk you through the step-by-step process of doing so.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/1*m7m6q9YviUJpp1jxQFB3aw.png" /></figure><h4>Setting up the web project</h4><p>Since we are using Blazor web assembly, we first initialize our web project by the following commands:</p><pre>dotnet new blazor -o NotesApp</pre><pre>cd BlazorApp</pre><p>Now we add code to the Home.razor file that represents the default home page of your web application. This file contains the markup and logic associated with the main content that users see when they navigate to the home or root URL of your application.</p><pre>@page &quot;/&quot;<br>@rendermode InteractiveServer<br>@using StickyNotes.Components.Components<br><br>&lt;PageTitle&gt;Home&lt;/PageTitle&gt;<br><br>&lt;button @onclick=&quot;AddNote&quot;&gt;Add Note&lt;/button&gt;<br>	<br>@foreach (var note in notes)<br>{<br>    &lt;Note OnDelete=&quot;() =&gt; DeleteNote(note)&quot; /&gt;<br>}<br><br>@code {<br>    private List&lt;NoteModel&gt; notes = new List&lt;NoteModel&gt;();<br><br>    private void AddNote()<br>    {<br>        notes.Add(new NoteModel());<br>   		StateHasChanged();<br>    }<br><br>    private void DeleteNote(NoteModel noteToDelete)<br>    {<br>        notes.Remove(noteToDelete);<br>    }<br><br>    private class NoteModel { }</pre><p>Then we add this code to Note.razor file which provides a user interface for creating and deleting notes.</p><pre>@code {<br>    private string noteContent;<br>}<br><br>&lt;div class=&quot;note-container&quot;&gt;<br>    &lt;textarea @bind=&quot;noteContent&quot; placeholder=&quot;Write your note here...&quot;&gt;&lt;/textarea&gt;<br>    &lt;button @onclick=&quot;DeleteNote&quot;&gt;Delete Note&lt;/button&gt;<br>&lt;/div&gt;<br><br>@code {<br>    // You can define an EventCallback if you want to notify a parent component<br>    [Parameter]<br>    public EventCallback OnDelete { get; set; }<br><br>    private void DeleteNote()<br>    {<br>        // Logic to delete the note<br>        // If this component is part of a collection, you might want to call OnDelete to notify the parent to remove it<br>        OnDelete.InvokeAsync(null);<br>    }<br>}</pre><p>If you like you can find the source code of this project <a href="https://github.com/Hafsa-jabeen/Notes">here</a>.</p><h4>Running the project in Codesphere</h4><p>To get this project running on Codesphere, you can create an empty working space and import the code from GitHub.</p><p>Then you would need to set the dotnet environment and run these commands:</p><p>Now we download the dotnet installer for Linux using wget.</p><pre>wget https://dot.net/v1/dotnet-install.sh -O dotnet-install.sh</pre><p>Next, we assign it the roles that are necessary to run the application.</p><pre>chmod +x ./dotnet-install.sh</pre><p>Now add this command to install dotnet.</p><pre>./dotnet-install.sh --version latest --install-dir /home/user/app/.dotnet --no-path</pre><p>The next step is to change the default port from “5000” to “3000” in /Properties/launchSettings.json</p><pre>&quot;applicationUrl&quot;: &quot;http://0.0.0.0:3000&quot;,</pre><p>Now we use the run command</p><pre>/home/user/app/.dotnet/dotnet watch</pre><p>This will launch the web app.</p><p>Alternatively, you can find a preconfigured version of this application in our templates. You can create a workspace and from the drop-down choose this template. You will have all these commands in the CI pipeline.</p><p>To understand how you can run a CI pipeline head over to <a href="https://codesphere.com/articles/angular-template">Creating an Angular Template for Codesphere</a>.</p><p>I hope you found this article useful, stay tuned for more.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=34f298ab3816" width="1" height="1" alt=""><hr><p><a href="https://medium.com/codesphere-cloud/building-a-beginner-friendly-c-application-34f298ab3816">Building a beginner-friendly C# application</a> was originally published in <a href="https://medium.com/codesphere-cloud">Codesphere</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Getting started with Stable Diffusion Text2Img AI]]></title>
            <link>https://medium.com/codesphere-cloud/getting-started-with-stable-diffusion-text2img-ai-7f90ccc5ac95?source=rss-86282414923b------2</link>
            <guid isPermaLink="false">https://medium.com/p/7f90ccc5ac95</guid>
            <category><![CDATA[prompt-engineering]]></category>
            <category><![CDATA[tutorial]]></category>
            <category><![CDATA[stable-diffusion]]></category>
            <category><![CDATA[text2image]]></category>
            <dc:creator><![CDATA[Codesphere]]></dc:creator>
            <pubDate>Mon, 13 Nov 2023 16:19:15 GMT</pubDate>
            <atom:updated>2023-11-13T16:19:15.875Z</atom:updated>
            <content:encoded><![CDATA[<p>Stable diffusion has become the staple of open source image generation AI. Similar to Llama anyone can use and work with the stable diffusion code. Tons of other open source projects build on top of it.</p><p>Generally you can use stable diffusion &amp; related models to either generate images from prompts or edit images with prompts (text2img or img2img).</p><h4>Running stable diffusion</h4><p>The most comfortable way to work with stable diffusion is via the open source webUI <a href="https://github.com/AUTOMATIC1111/stable-diffusion-webui">https://github.com/AUTOMATIC1111/stable-diffusion-webui</a>. Unlike other alternatives that require deeper understanding of the underlying code and working with command line prompts — this webUI comes with a 1-click installer and a web view with all the configuration options you might need. You can run it locally (if you have a strong graphics card &amp; CPU) or run it via a cloud provider that offers GPU environments. If you’re looking for free cloud GPU’s check out our comparison article here <a href="https://codesphere.com/articles/5-best-free-cloud-gpu-providers-for-hobbyists">https://codesphere.com/articles/5-best-free-cloud-gpu-providers-for-hobbyists</a></p><p>If you are using Codesphere to deploy your stable diffusion webUI you can use our template.</p><p>After running the installation (which takes a few minutes) and your run pipeline you should see a WebUI similar to this one.</p><h4>How to write good text to image prompts</h4><p>This is the typical way of working with generative image AI. You provide a prompt describing visually what you expect to see in the image and the AI takes the input, tries to find semantically similar images from its training data and merges them into an image.</p><p>As you can see there is a wide array of settings available in the webUI and after playing around with it for a bit you will see that results differ dramatically.</p><p>Generating usable images from this requires mainly two things:</p><ol><li>A good prompt with relevant context</li><li>Settings appropriate for your use case (there is a trade-off between generation speed &amp; quality — more below)</li></ol><p>Let’s look at some example prompts first:</p><p><strong><em>“Romantic painting of a ship sailing in a stormy sea, with dramatic lighting and powerful waves.</em></strong>”</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/768/1*KwAc9-nZ11vO9bRVRGkRgg.png" /></figure><p>This prompt is a good start because it visually describes key features, i.e. what style of image is expected (romantic painting), the main object (ship) and the surrounding with enough detail. Finding the right amount of details can be a bit tricky and might take some practice — in general if you describe clearly and unambiguously what you’d like to see as concise as possible you’ll get decent results.</p><p>Unfortunately the picture output doesn’t have much details yet:</p><p><strong><em>“best quality, masterpiece, (photorealistic:1.4), ship in stormy seas, (powerful waves:1.2), dramatic lighting, hyper quality, intricate detail, ultra realistic, maximum detail, foreground focus, instagram, 8k, volumetric light, cinematic, octane render, uplight, no blur, 8k”</em></strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/768/1*r8dllmgEcL3VCXDwdX6Oew.png" /></figure><p>Can we still improve the output? Yes! In order to understand what changed between the first prompt and the second prompt it is helpful to think about how stable diffusion and similar models are trained:</p><p>They get millions of labeled images of differing quality, assign patterns &amp; similarity through arranging vector representations of labels and images closer in proximity of each other if similar. Now we can trick the model to only look on a subset of the pictures it was trained on, namely those we associate with beauty. By adding comma separated attributes associated with high quality input (i.e. masterpiece or cinematic) we can improve the output significantly. You can also add weights (i.e. photorealistic:1.4) if you want to prioritize between different attributes.</p><p><strong><em>“best quality, masterpiece, (photorealistic:1.4), ship in stormy seas, (powerful waves:1.2), dramatic lighting, hyper quality, intricate detail, ultra realistic, maximum detail, foreground focus, instagram, 8k, volumetric light, cinematic, octane render, uplight, no blur, 8k”</em></strong></p><p>&amp; negative prompt:</p><p><strong><em>“nsfw, ng_deepnegative_v1_75t,badhandv4, (worst quality:2), (low quality:2), (normal quality:2), lowres,watermark, monochrome”</em></strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/768/1*MtauP2X1NtosrtVmCoBs_A.png" /></figure><p>Another great way to improve an already excellent output image is by specifying attributes and output visual you want to avoid. Your frontend provides a second box for this. By adding quality descriptions like low and normal to the negative prompt we can enforce the ultra high quality even stronger. By adding thing like monochrome &amp; watermark we can enforce more variation in our output.</p><h4>Text 2 image settings</h4><p>As mentioned there is a ton of different settings so we will focus on the important ones here:</p><p><strong>Sampling method</strong></p><p>The default is DPM++ 2M Karras which is a great mix between speed &amp; quality. If you have time and want a bit more detail try switching to DPM++ SDE Karras</p><p>Other choices include some that are a lot faster like UniPC at the expense of detail</p><p><strong>Hires. fix</strong></p><p>This handles the upscaling of your output images. Per default images are 512x512 pixels which is the size of the training images used. You can upscale your images to higher resolution at the cost of speed. I recommend a value between 1.5 and 1.7 anything higher will get critically slow and might even crash the GPU with a out of memory error.</p><p><strong>Refiner</strong></p><p>This allows you to add a second model that takes the output of the first model and refines it.</p><p>That’s a wrap — What are you going to create with this fascinating new technology?</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=7f90ccc5ac95" width="1" height="1" alt=""><hr><p><a href="https://medium.com/codesphere-cloud/getting-started-with-stable-diffusion-text2img-ai-7f90ccc5ac95">Getting started with Stable Diffusion Text2Img AI</a> was originally published in <a href="https://medium.com/codesphere-cloud">Codesphere</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Getting started with Jupyter Notebooks in Codesphere]]></title>
            <link>https://medium.com/codesphere-cloud/getting-started-with-jupyter-notebooks-in-codesphere-48f956eec0d4?source=rss-86282414923b------2</link>
            <guid isPermaLink="false">https://medium.com/p/48f956eec0d4</guid>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[jupyter]]></category>
            <category><![CDATA[notebook]]></category>
            <category><![CDATA[machine-learning]]></category>
            <dc:creator><![CDATA[Codesphere]]></dc:creator>
            <pubDate>Fri, 27 Oct 2023 15:35:14 GMT</pubDate>
            <atom:updated>2023-10-27T15:35:14.658Z</atom:updated>
            <content:encoded><![CDATA[<h3>Getting started with Jupyter Notebooks in AI</h3><p>Jupyter notebooks have been around for a while but that hasn’t hurt their popularity one bit. Especially the AI and ML community have been heavy users.</p><p>The amazing thing about Jupyter notebooks is the way it combines a doc like UI where you can add cells that execute any code you throw at it, most common languages are Python, R and Julia but there are a lot of kernels options out there thanks to the reliable open source community. It’s about time that we added support for it to Codesphere and explored some use cases.</p><figure><img alt="Codesphere &amp; Jupyter Logo" src="https://cdn-images-1.medium.com/max/1024/1*r-gm3DJmFqCNxiMTO4KAgw.png" /></figure><h4>Getting started with Jupyter in Codesphere</h4><p>First you’ll want to create a new empty workspace (or clone a repo with your existing notebooks of course). Since we will be using Python inside the notebook (which requires Python 3.9 or higher) we will need to update Python first.</p><p>[Workaround] If you want your python version to persist across workspace restarts currently you are required to set the following environment variable (via setup/env vars)</p><p>Key:</p><pre>PYENV_ROOT</pre><p>Value:</p><pre>/home/user/app/.pyenv</pre><p>This will ensure the python version selection gets stored in the persistent app directory. Afterwards open a new terminal (Do not use existing terminals as they are missing the environment variable you just set) — in this new terminal type</p><pre>pipenv install jupyter --python 3.9.11</pre><p>When prompted to confirm whether you want to install the new Python version confirm with Y. Wait till all the dependencies were added successfully - this might take a minute.</p><p>Afterwards either activate your pipenv via pipenv shell followed by a jupyter notebook or run</p><pre>pipenv run juptyer notebook</pre><p>Now you can open the deployment with the icon in the top right corner. Per default Notebooks are secured by a password / token mechanism — this ensure’s that only you and your team have access to the notebook server.</p><figure><img alt="Get your notebook’s token from the terminal" src="https://cdn-images-1.medium.com/max/1024/1*XH4kgTrMNWaYo7jG1hLtcA.jpeg" /></figure><p>That means also you will initially authenticate yourself as the owner of this notebook server with a token — your specific token will be printed in the terminal output of the last command you ran. Copy the token and insert it into the webUI of your notebook server. Ideally you use this opportunity to set a new password you can remember, then you won’t need to copy the token from the terminal the next time you come back.</p><p>After providing your token you should be greeted by the Notebook Server UI that contains all the files in your directory. If you started with an empty workspace you should only find the pipenv files here. Right click anywhere in the UI and select new notebook. This will open a new tab in your browser with an untitled and empty jupyter notebook. You still need to select the kernel, for this simple example we’ll go with the default iPython kernel.</p><h4>Notebook basics (skip ahead to use cases if you are familiar with notebooks already)</h4><p>Notebooks are organized in cells and there are 3 types of cells:</p><ol><li>Code cells</li><li>Markdown cells</li><li>Raw text cells</li></ol><p>Code cells contain your python code or terminal commands like pip install pandas and can be executed one by one. You can run a single cell multiple times and if the code you ran contains terminal output the notebook frontend will display the output below the cell. Likewise if your code doesn&#39;t run through because of unhandled errors it will display these below the respective cell.</p><p>Markdown cells on the other hand contain markdown formatted text. This is great for creating interactive documents that allow others (or yourself in the future) to follow along and understand why you built the code blocks the way you did.</p><p>Try adding some Python code to the first cell and click the play icon in the menu.</p><pre>print(&quot;Hello this code was excecuted in a jupyter cell&quot;)</pre><p>You should see whatever text you put inside the “” of the print statement below the cell.</p><p>If you want to use a markdown cell instead, select the cell and switch the from code to markdown. If you enter valid markdown notion and run the cell you will get formatted text in return.</p><h4>Use case — Running your own open-source DALL-E alternative</h4><p>For this example we will run a Text to image AI. It requires a notebook on one of our GPU plans — free BETA available through special signup link: <a href="https://ai.codesphere.com/">https://ai.codesphere.com/</a></p><p>We will be using this performance optimized version of stable diffusion <a href="https://huggingface.co/segmind/SSD-1B">https://huggingface.co/segmind/SSD-1B</a> because that is small enough to be run on our free tier GPU.</p><p>In your notebook you need to add &amp; execute the following code cells:</p><pre>pip install git+https://github.com/huggingface/diffusers</pre><pre>pip install transformers accelerate safetensors</pre><pre>from diffusers import StableDiffusionXLPipeline<br>import torch<br>pipe = StableDiffusionXLPipeline.from_pretrained(&quot;segmind/SSD-1B&quot;, torch_dtype=torch.float16, use_safetensors=True, variant=&quot;fp16&quot;)<br>pipe.to(&quot;cuda&quot;)<br># if using torch &lt; 2.0<br># pipe.enable_xformers_memory_efficient_attention()<br>prompt = &quot;A glamorous ski town in the Swiss alps in the 80s. A retro fotograph style picture with street lights, fancy cars and snowy mountains in the background and fancy dressed people enjoying a hot drink outside.&quot; # Your prompt here<br>neg_prompt = &quot;ugly, blurry, poor quality&quot; # Negative prompt here<br>image = pipe(prompt=prompt, negative_prompt=neg_prompt).images[0]</pre><pre>image</pre><p>Prepare to be amazed! The output is a beautiful and stunning scene it feels as if we where there in 1980s Zermatt 💜 You can hold shift+right click on the image to copy or save it from the notebook to your laptop.</p><figure><img alt="Stable-diffusion example images" src="https://cdn-images-1.medium.com/max/1024/1*psLMWIvHH-IcGVx0G5LKHw.jpeg" /></figure><p>And just for the fun of it, you don’t even have to come up with the detailed prompts yourself — ask chatGPT or your trusted self hosted Llama to to help with the prompts:</p><p>“I need your help to write prompts for a stable diffusion text to image generator. The goal is to generate a series of images that are detail rich, have a cosy atmosphere and a retro look.<br>Can you describe this “A glamorous ski town in the Swiss alps in the 80s. A retro fotograph style picture with street lights, fancy cars and snowy mountains in the background and fancy dressed people enjoying a hot drink outside.” from multiple angles and perspectives so that I can plug each prompt into the image generator?”</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/320/1*QDawTvHLrjLSn3TJgs5SuQ.jpeg" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/320/1*UtRg2pB1M4X5BgSUiLws-g.jpeg" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/320/1*-a0SaPZKW4-LxrdbkFzoig.jpeg" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/320/1*XkqBZqJffbpTOI1guJbn3g.jpeg" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/320/1*VOONyRJBXp20RwSz_jlwVA.jpeg" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/320/1*8ulyGhYyxYqbnGqI19XWkQ.jpeg" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/320/1*0p2hYunhiqEI5iwLFwlrNA.jpeg" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/320/1*5Ux4TIA8TRa9_I8AFtLiTg.jpeg" /></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=48f956eec0d4" width="1" height="1" alt=""><hr><p><a href="https://medium.com/codesphere-cloud/getting-started-with-jupyter-notebooks-in-codesphere-48f956eec0d4">Getting started with Jupyter Notebooks in Codesphere</a> was originally published in <a href="https://medium.com/codesphere-cloud">Codesphere</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>