<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: shunnNet</title>
    <description>The latest articles on Forem by shunnNet (@shunnnet).</description>
    <link>https://forem.com/shunnnet</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F583407%2F197ef2bd-7a13-463f-abf4-63ea807cd2fe.jpeg</url>
      <title>Forem: shunnNet</title>
      <link>https://forem.com/shunnnet</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/shunnnet"/>
    <language>en</language>
    <item>
      <title>Introducing Vue Modal Route</title>
      <dc:creator>shunnNet</dc:creator>
      <pubDate>Sun, 04 May 2025 04:47:39 +0000</pubDate>
      <link>https://forem.com/shunnnet/implementing-vue-modal-route-58ff</link>
      <guid>https://forem.com/shunnnet/implementing-vue-modal-route-58ff</guid>
      <description>&lt;p&gt;&lt;a href="https://github.com/shunnNet/vue-modal-route" rel="noopener noreferrer"&gt;vue-modal-route&lt;/a&gt; is a package based on Vue 3 and vue-router, implementing the concept of modal routes.&lt;/p&gt;

&lt;p&gt;It does not include any Modal UI components—only handling visibility states, state passing, etc. This makes it possible to integrate with any library that provides Modal components.&lt;/p&gt;

&lt;p&gt;You can now play with it in &lt;a href="https://stackblitz.com/~/github.com/shunnNet/vmrh-vite-playground" rel="noopener noreferrer"&gt;online playground&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a modal route?
&lt;/h2&gt;

&lt;p&gt;When I say "modal route," I mean a scenario where opening a modal causes the URL to change. You might have heard of or experienced what's called a &lt;code&gt;Twitter-style modal&lt;/code&gt;, which is a good example of this. Moreover, when you directly visit that URL, you see the modal's content as a full page instead of a modal.&lt;/p&gt;

&lt;p&gt;This kind of modal route can be easily implemented in Next.js using Parallel Routes. In Nuxt.js, you can use &lt;a href="https://nuxt-pages-plus.pages.dev/routing/modal-routes" rel="noopener noreferrer"&gt;Nuxt Pages Plus&lt;/a&gt; to achieve this.&lt;/p&gt;

&lt;h2&gt;
  
  
  Motivation
&lt;/h2&gt;

&lt;p&gt;The idea to implement modal routes came from a user experience I had on an Android phone. When browsing a webpage on mobile, I often encounter modals that cover almost the entire screen. My instinct is to press the &lt;code&gt;&amp;lt;&lt;/code&gt; (back) button to exit the modal, but it ends up exiting the entire page instead, which is frustrating.&lt;/p&gt;

&lt;p&gt;On mobile web, the back action usually means going to the "previous page." To avoid this issue, the modal toggle should be tied to the page URL. Opening or closing a modal should be treated the same as navigating to or away from a page.&lt;/p&gt;

&lt;p&gt;This is why I need modal routes.&lt;/p&gt;

&lt;p&gt;Also, modals often need routing capabilities. For instance, have you ever had a requirement where a modal should automatically open when a user visits a URL with a specific query string? Or wanted to implement a multi-step process inside a modal but found it hard to integrate with &lt;code&gt;router-view&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;If we have modal routes, all of the above situations can be handled much more elegantly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Features and Implementation
&lt;/h2&gt;

&lt;p&gt;Although I mentioned &lt;code&gt;Twitter-style modal&lt;/code&gt; implementations, &lt;code&gt;@vmrh/modal-route&lt;/code&gt; is not a &lt;code&gt;Twitter-style modal&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Like &lt;code&gt;Twitter-style modals&lt;/code&gt;, the URL changes when the modal is opened. However, when you directly visit that URL, the content is still shown as a modal (possibly configurable in the future). In many situations, I think it’s more desirable to still present it as a modal instead of a full page. This feels more consistent with how most websites behave.&lt;/p&gt;

&lt;p&gt;Secondly, &lt;code&gt;@vmrh/modal-route&lt;/code&gt; allows you to pass complex objects when opening a modal—not just URL-compatible data. In other words, you can call &lt;code&gt;openModal({ user: UserObject })&lt;/code&gt; and pass any kind of data.&lt;/p&gt;

&lt;p&gt;I aim to make this package capable of handling all modal scenarios. Having some modals behave like routes and others not creates inconsistent user experiences, which is not ideal.&lt;/p&gt;

&lt;p&gt;Also, modals often require passing around various types of data, and what the URL can carry alone is not enough.&lt;/p&gt;

&lt;p&gt;Third, beyond the typical one-route-one-modal setup, &lt;code&gt;@vmrh/modal-route&lt;/code&gt; provides three types of modal routes to handle different modal scenarios:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Path modal&lt;/code&gt;: A modal specific to one page, similar to a typical modal route with a fixed URL.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Global modal&lt;/code&gt;: A modal that can appear on any page, like a login modal. Its route is dynamically appended to the current route.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Query modal&lt;/code&gt;: A functional modal (e.g., alert or confirm). When triggered, it shows a corresponding query string.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The History Challenge
&lt;/h2&gt;

&lt;p&gt;One major challenge with modal routes is dealing with &lt;code&gt;window.history&lt;/code&gt;. While the goal is to integrate with the browser history for a smoother UX, this integration also causes complications.&lt;/p&gt;

&lt;p&gt;When a modal opens, the corresponding URL should reflect that change. To allow the user to close the modal using the "Back" button, we use &lt;code&gt;router.push&lt;/code&gt; when opening. But how should we close it?&lt;/p&gt;

&lt;p&gt;Let’s go through a few scenarios using three modals: A, B, and C on the &lt;code&gt;/home&lt;/code&gt; page.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A: &lt;code&gt;/home/A&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;B: &lt;code&gt;/home/B&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;C: &lt;code&gt;/home/A/C&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Scenario 1: /home -&amp;gt; /home/modal-a
&lt;/h3&gt;

&lt;p&gt;When the user is on /home and clicks a button to open modal &lt;code&gt;A&lt;/code&gt;, the URL changes to &lt;code&gt;/home/modal-a&lt;/code&gt;. At this point, using "go back" will return to &lt;code&gt;/home&lt;/code&gt;, thereby closing modal A. But if the user clicks the "Close" button to close modal A manually, the question is:&lt;/p&gt;

&lt;p&gt;Should we...&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;push to /home, or&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;back to /home?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I choose to back to &lt;code&gt;/home&lt;/code&gt;, because this aligns with the browser history state as if the user simply clicked the "back" button.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="p"&gt;1.&lt;/span&gt; Modal A Open&lt;span class="sb"&gt;

              v ----------&amp;gt; V
&lt;/span&gt;(page) --&amp;gt; /home -&amp;gt; /home/modal-a
&lt;span class="p"&gt;
---&lt;/span&gt;
&lt;span class="p"&gt;2.&lt;/span&gt; Close modal with &lt;span class="sb"&gt;`Prev step`

             V &amp;lt;----------- v
&lt;/span&gt;(page) --&amp;gt; /home -&amp;gt; /home/modal-a
&lt;span class="p"&gt;
--- 
&lt;/span&gt;
2-1. Close modal with &lt;span class="sb"&gt;`.push`

                            v -------&amp;gt; V
&lt;/span&gt;(page) --&amp;gt; /home -&amp;gt; /home/modal-a -&amp;gt; /home
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If &lt;code&gt;.push&lt;/code&gt; is used, the user technically returns to &lt;code&gt;/home&lt;/code&gt;, but when they try to go "back" again to get to the previous (page), they end up back at &lt;code&gt;A&lt;/code&gt;. This creates an inconsistent experience.&lt;/p&gt;

&lt;p&gt;I believe that when the user closes a modal, they naturally expect to be exiting the modal, not creating a new entry in the history stack.&lt;/p&gt;

&lt;p&gt;Therefore, when the user "closes" a modal, the app should back to &lt;code&gt;/home&lt;/code&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  Scenario 2: &lt;code&gt;/home → /home/modal-a → /home/modal-a/modal-c&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Continuing from Scenario 1, the user first clicks a button on &lt;code&gt;/home&lt;/code&gt; to open modal &lt;code&gt;A&lt;/code&gt;, changing the URL to &lt;code&gt;/home/modal-a&lt;/code&gt;. Then, they click a button inside &lt;code&gt;A&lt;/code&gt; to open modal &lt;code&gt;C&lt;/code&gt;, updating the URL to &lt;code&gt;/home/modal-a/modal-c&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Since &lt;code&gt;/home/modal-a/modal-c&lt;/code&gt; is a child route of &lt;code&gt;/home/modal-a&lt;/code&gt;, modal &lt;code&gt;A&lt;/code&gt; remains visible in the background while modal &lt;code&gt;C&lt;/code&gt; appears on top of it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="p"&gt;1.&lt;/span&gt; Modal A Open&lt;span class="sb"&gt;

            v -----------&amp;gt; V
&lt;/span&gt;(page) --&amp;gt; /home -&amp;gt; /home/modal-a
&lt;span class="p"&gt;
2.&lt;/span&gt; Modal C Open&lt;span class="sb"&gt;

             v -----------&amp;gt; v ---------------------&amp;gt; V
&lt;/span&gt;(page) --&amp;gt; /home -&amp;gt; /home/modal-a -&amp;gt; /home/modal-a/modal-c
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This scenario is similar to Scenario 1 but better highlights the inconsistency caused by using &lt;code&gt;.push&lt;/code&gt; to close a modal.&lt;/p&gt;

&lt;p&gt;If &lt;code&gt;.push&lt;/code&gt; is used to close &lt;code&gt;C&lt;/code&gt;, returning to &lt;code&gt;A&lt;/code&gt; creates a situation where the "previous step" no longer closes &lt;code&gt;A&lt;/code&gt;, but instead reopens modal &lt;code&gt;C&lt;/code&gt;. That’s because "going back" would now return to &lt;code&gt;/home/modal-a/modal-c&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="p"&gt;1.&lt;/span&gt; Close Modal C by &lt;span class="sb"&gt;`.push`

             v -----------&amp;gt; v ---------------------&amp;gt; v --------------&amp;gt; V
&lt;/span&gt;(page) --&amp;gt; /home -&amp;gt; /home/modal-a -&amp;gt; /home/modal-a/modal-c -&amp;gt; /home/modal-a
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Therefore, when the user "closes" a modal, we should use back to return to the previous step, ensuring a proper modal closing experience.&lt;/p&gt;




&lt;h3&gt;
  
  
  Scenario 3: &lt;code&gt;/home → /home/modal-a → /home/modal-b&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Now let’s look at a slightly more unusual case.&lt;/p&gt;

&lt;p&gt;Both modals &lt;code&gt;A&lt;/code&gt; and &lt;code&gt;B&lt;/code&gt; exist on the &lt;code&gt;/home&lt;/code&gt; page. After entering &lt;code&gt;/home&lt;/code&gt;, the user clicks a button that opens modal &lt;code&gt;A&lt;/code&gt;. Then, from within modal &lt;code&gt;A&lt;/code&gt;, the user clicks another button that opens modal &lt;code&gt;B&lt;/code&gt;. Since this navigates away from &lt;code&gt;/home/modal-a&lt;/code&gt;, modal &lt;code&gt;A&lt;/code&gt; is closed, leaving only modal &lt;code&gt;B&lt;/code&gt; visible on the screen.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="p"&gt;1.&lt;/span&gt; Modal A Open&lt;span class="sb"&gt;

              v -----------&amp;gt; V
&lt;/span&gt;(page) --&amp;gt; /home -&amp;gt; /home/modal-a
&lt;span class="p"&gt;
2.&lt;/span&gt; Modal B Open&lt;span class="sb"&gt;

             v -----------&amp;gt; v -------------&amp;gt; V
&lt;/span&gt;(page) --&amp;gt; /home -&amp;gt; /home/modal-a -&amp;gt; /home/modal-b
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point, what should happen when the user goes "back" or clicks "close"?&lt;/p&gt;

&lt;p&gt;Following the logic from Scenario 1, both "close" and "back" mean going back one step in history. So, it might make sense to return to &lt;code&gt;/home/modal-a&lt;/code&gt; and reopen modal &lt;code&gt;A&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But from another perspective, when a modal is opened on a page and the user clicks the &lt;code&gt;"X"&lt;/code&gt; to close it, the common user expectation—based on typical web interactions—is to return directly to &lt;code&gt;/home&lt;/code&gt;. From a visual experience standpoint, this feels more intuitive.&lt;/p&gt;

&lt;p&gt;Both behaviors are valid and could make sense in different contexts. However, the latter (returning to &lt;code&gt;/home&lt;/code&gt;) aligns better with modern UX conventions. Therefore, &lt;code&gt;@vmrh/modal-route&lt;/code&gt; chooses this as the default behavior.&lt;/p&gt;

&lt;p&gt;Wait a second—return to &lt;code&gt;/home&lt;/code&gt;? Didn't we say earlier that "close" or "back" should simply go back one history entry? That would return to &lt;code&gt;/home/modal-a&lt;/code&gt;, not &lt;code&gt;/home&lt;/code&gt;. So how do we end up at &lt;code&gt;/home&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;&lt;code&gt;@vmrh/modal-route&lt;/code&gt; rewrites the history stack during modal opening and closing through a sequence of actions to fulfill this behavior:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="p"&gt;1.&lt;/span&gt; Modal A Open&lt;span class="sb"&gt;

              v -----------&amp;gt; V
&lt;/span&gt;(page) --&amp;gt; /home -&amp;gt; /home/modal-a
&lt;span class="p"&gt;
2.&lt;/span&gt; Modal B Open - 1. &lt;span class="sb"&gt;`.back()`&lt;/span&gt; to &lt;span class="sb"&gt;`/home`

             V &amp;lt;----------- v 
&lt;/span&gt;(page) --&amp;gt; /home -&amp;gt; /home/modal-a
&lt;span class="p"&gt;
3.&lt;/span&gt; Modal B Open - 2. &lt;span class="sb"&gt;`.push()`&lt;/span&gt; to &lt;span class="sb"&gt;`/home/modal-b`

             v ----------&amp;gt; V 
&lt;/span&gt;(page) --&amp;gt; /home -&amp;gt; /home/modal-b
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;@vmrh/modal-route&lt;/code&gt; calculates the common ancestor route of the two modals, first using &lt;code&gt;.back()&lt;/code&gt; to return to the shared base (&lt;code&gt;/home&lt;/code&gt;), then &lt;code&gt;.push()&lt;/code&gt; to navigate to the target modal route. As a result, when you open &lt;code&gt;/home/modal-b&lt;/code&gt;, closing it or going "back" will return you to &lt;code&gt;/home&lt;/code&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Scenario 4: &lt;code&gt;/home/modal-a/modal-c&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;What if we skip &lt;code&gt;A&lt;/code&gt; and directly go to &lt;code&gt;C&lt;/code&gt;? Both &lt;code&gt;A&lt;/code&gt; and &lt;code&gt;C&lt;/code&gt; show up since &lt;code&gt;C&lt;/code&gt; is a child of &lt;code&gt;A&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="p"&gt;1.&lt;/span&gt; Modal C Open&lt;span class="sb"&gt;

              v ------------------&amp;gt; V
&lt;/span&gt;(page) --&amp;gt; /home -&amp;gt; /home/modal-a/modal-c
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Should closing &lt;code&gt;C&lt;/code&gt; go back to &lt;code&gt;A&lt;/code&gt; or to &lt;code&gt;/home&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;Default behavior is to go back to &lt;code&gt;A&lt;/code&gt;. This is achieved by inserting intermediate history entries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="p"&gt;1.&lt;/span&gt; Modal C Open - (1) &lt;span class="sb"&gt;`.push`&lt;/span&gt; to &lt;span class="sb"&gt;`/home/modal-a`

              v ----------&amp;gt; V
&lt;/span&gt;(page) --&amp;gt; /home -&amp;gt; /home/modal-a
&lt;span class="p"&gt;
2.&lt;/span&gt; Modal C Open - (2) &lt;span class="sb"&gt;`.push`&lt;/span&gt; to &lt;span class="sb"&gt;`/home/modal-a/modal-c`

              v ----------&amp;gt; v ---------------------&amp;gt; V
&lt;/span&gt;(page) --&amp;gt; /home -&amp;gt; /home/modal-a -&amp;gt; /home/modal-a/modal-c
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So "Back" from &lt;code&gt;C&lt;/code&gt; still lands on &lt;code&gt;A&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If &lt;code&gt;A&lt;/code&gt; is closed while on a child route, it still goes back to &lt;code&gt;/home&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="p"&gt;1.&lt;/span&gt; Modal A Open - &lt;span class="sb"&gt;`.push`&lt;/span&gt; to &lt;span class="sb"&gt;`/home/modal-a`&lt;/span&gt;
              3             4
              v ----------&amp;gt; V
(page) --&amp;gt; /home -&amp;gt; /home/modal-a
&lt;span class="p"&gt;
2.&lt;/span&gt; Go to A's child path - &lt;span class="sb"&gt;`.push`&lt;/span&gt; to &lt;span class="sb"&gt;`/home/modal-a/child`&lt;/span&gt;
              3             4                        5
              v ----------&amp;gt; v ---------------------&amp;gt; V
(page) --&amp;gt; /home -&amp;gt; /home/modal-a -&amp;gt; /home/modal-a/child
&lt;span class="p"&gt;
3.&lt;/span&gt; Close A: &lt;span class="sb"&gt;`.back(5 - 3)`&lt;/span&gt;
              3              4                       5
              v &amp;lt;----------------------------------- V
(page) --&amp;gt; /home -&amp;gt; /home/modal-a -&amp;gt; /home/modal-a/child
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Scenario 5: &lt;code&gt;/home/modal-b&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;What if the user enters the site directly at &lt;code&gt;/home/modal-b&lt;/code&gt;?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="p"&gt;1.&lt;/span&gt; Enter &lt;span class="sb"&gt;`/home/modal-b`&lt;/span&gt;
                 V
(??) --&amp;gt; /home/modal-b
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We likely want the user to remain on the site after closing the modal. But if we just back, they’ll leave the site.&lt;/p&gt;

&lt;p&gt;You might think we could manipulate history when entering:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="p"&gt;1.&lt;/span&gt; Modal b Open - (1) enter website&lt;span class="sb"&gt;

                 V
&lt;/span&gt;(??) --&amp;gt; /home/modal-b
&lt;span class="p"&gt;
2.&lt;/span&gt; Modal b Open - (2) replace &lt;span class="sb"&gt;`/home/modal-b`&lt;/span&gt; to &lt;span class="sb"&gt;`/home`

              V
&lt;/span&gt;(page) --&amp;gt; /home
&lt;span class="p"&gt;
3.&lt;/span&gt; Modal b Open - (3) &lt;span class="sb"&gt;`.push()`&lt;/span&gt; to &lt;span class="sb"&gt;`/home/modal-b`

              v ----------&amp;gt; V
&lt;/span&gt;(page) --&amp;gt; /home -&amp;gt; /home/modal-b
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But due to browser optimization, &lt;code&gt;.push&lt;/code&gt; becomes &lt;code&gt;.replace&lt;/code&gt; if no user interaction has occurred. So history remains:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;                   V
(page) --&amp;gt; /home/modal-b
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thus, &lt;code&gt;@vmrh/modal-route&lt;/code&gt; modifies history when closing the modal instead:&lt;br&gt;
&lt;code&gt;@vmrh/modal-route&lt;/code&gt; in the above scenario rewrites the history when the modal is "closed".&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="p"&gt;1.&lt;/span&gt; Modal B Open - enter website&lt;span class="sb"&gt;

                 V
&lt;/span&gt;(??) --&amp;gt; /home/modal-b
&lt;span class="p"&gt;
--- &lt;/span&gt;
&lt;span class="p"&gt;2.&lt;/span&gt; Modal B Close - (1) replace &lt;span class="sb"&gt;`/home/modal-b`&lt;/span&gt; with &lt;span class="sb"&gt;`/home`

              V
&lt;/span&gt;(page) --&amp;gt; /home
&lt;span class="p"&gt;
--- &lt;/span&gt;
&lt;span class="p"&gt;3.&lt;/span&gt; Modal B Close - (2) &lt;span class="sb"&gt;`.push()`&lt;/span&gt; to &lt;span class="sb"&gt;`/home/modal-b`

              v ----------&amp;gt; V
&lt;/span&gt;(page) --&amp;gt; /home -&amp;gt; /home/modal-b
&lt;span class="p"&gt;
--- &lt;/span&gt;
&lt;span class="p"&gt;4.&lt;/span&gt; Modal B Close - (3) &lt;span class="sb"&gt;`.back()`&lt;/span&gt; to &lt;span class="sb"&gt;`/home`

              v ----------&amp;gt; V
&lt;/span&gt;(page) --&amp;gt; /home -&amp;gt; /home/modal-b
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This makes it possible to "close" modal &lt;code&gt;B&lt;/code&gt; while still staying within the website.&lt;/p&gt;

&lt;p&gt;However, when modal &lt;code&gt;B&lt;/code&gt; is open, pressing "back" may exit the website. This is because Vue Router cannot prevent the "back" action from leaving the site.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;Although &lt;code&gt;@vmrh/modal-route&lt;/code&gt; involves some special history manipulations under the hood, its default behavior is almost indistinguishable from a regular modal toggle on a webpage. Therefore, it can be used as a typical modal state controller — with the added feature of modal-route functionality: enabling "back to close" behavior.&lt;/p&gt;

&lt;p&gt;Optional behaviors can also be enabled, such as allowing the modal to open when directly entering the webpage. However, enabling such features introduces new details that need to be considered and handled. In the future, this package will offer more of these customizable behaviors.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/shunnNet/vue-modal-route" rel="noopener noreferrer"&gt;https://github.com/shunnNet/vue-modal-route&lt;/a&gt;&lt;/p&gt;

</description>
      <category>vue</category>
      <category>webdev</category>
    </item>
    <item>
      <title>✨ Co - A frontend development AI which create and write the content of the referenced files.</title>
      <dc:creator>shunnNet</dc:creator>
      <pubDate>Sun, 09 Feb 2025 15:53:08 +0000</pubDate>
      <link>https://forem.com/shunnnet/co-a-development-ai-which-create-and-write-the-content-of-the-referenced-files-4a0i</link>
      <guid>https://forem.com/shunnnet/co-a-development-ai-which-create-and-write-the-content-of-the-referenced-files-4a0i</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;Co is a frontend development AI writing assistant, similar to Copilot but with a different working approach, will automatically create and write the content of the referenced files in the code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;✨ Auto write/rewrite when you import a module (with special comments)&lt;/li&gt;
&lt;li&gt;🌴 Generate a project by markdown&lt;/li&gt;
&lt;li&gt;🛠️ TDD: auto generate implementation when writing test cases.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;Using OpenAI &lt;code&gt;gpt-4o-mini&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Click image to see the demo.&lt;/p&gt;

&lt;h3&gt;
  
  
  Vue - Write a simple page
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://youtu.be/IGBJbUESEtk" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9687zy7ll2mim9fw98fk.jpg" alt="Vue demo" width="800" height="450"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Vue - Write autocomplete input
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://youtu.be/Hfavj2m1o1s" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmcrtvzcqkeib1hec39t9.jpg" alt="AutoComplete demo" width="800" height="450"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Markdown: Generate a project
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://youtu.be/4XRZIQb3YOk" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F41j54bfoms0idzxvkrcv.jpg" alt="Markdown demo" width="800" height="450"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  TDD
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://youtu.be/cWDb-U3fImM" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd9zimr8fv44rk5660gf9.jpg" alt="TDD demo" width="800" height="450"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Quick start
&lt;/h2&gt;

&lt;p&gt;Install the package.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @imaginary-ai/core
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create &lt;code&gt;co.config.{js|ts}&lt;/code&gt; in current working directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// co.config.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;OpenAITextGenerator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;defineCoConfig&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@imaginary-ai/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineCoConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;baseDir&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;**/*.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;**/*.ts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;**/*.md&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;excludes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;**/node_modules/**&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;**/.vscode&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;**/.git/**&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;**/ai.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;generator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;OpenAITextGenerator&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Put your OPENAI_API_KEY here&lt;/span&gt;
    &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gpt-4o-mini&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;temperature&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}),&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Write some code import a function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// @co:&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;sayHello&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./path-to-file.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="c1"&gt;// @co-end&lt;/span&gt;

&lt;span class="nf"&gt;sayHello&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Go to terminal run &lt;code&gt;npx co run&lt;/code&gt;, then &lt;code&gt;path-to-file.js&lt;/code&gt; will be generated.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// path-to-file.js&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;sayHello&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello, World!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Usage
&lt;/h2&gt;

&lt;p&gt;Check &lt;a href="https://github.com/shunnNet/co?tab=readme-ov-file#usage" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; for more usages.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why &lt;code&gt;Co&lt;/code&gt; ?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Small Issues with Copilot
&lt;/h3&gt;

&lt;p&gt;I believe many people have used &lt;code&gt;GitHub Copilot&lt;/code&gt; or similar code assistants. Personally, I use &lt;code&gt;GitHub Copilot&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The feature I use most frequently in &lt;code&gt;GitHub Copilot&lt;/code&gt; is autocomplete. While editing a file, the model predicts the next content and provides suggestions.&lt;/p&gt;

&lt;p&gt;This truly deserves the name Copilot—it always lends a helping hand just when you’re feeling exhausted from coding. I often find myself genuinely grateful for it in those moments. At this point, I’ve gotten so used to autocomplete suggestions that it feels strange when they don’t appear.&lt;/p&gt;

&lt;p&gt;Within a single file, it often does a good job predicting what I need. However, things get a bit awkward when working across multiple files.&lt;/p&gt;

&lt;p&gt;For example, while writing File A, I realize I need a File B containing some functions to complete my work in File A.&lt;/p&gt;

&lt;p&gt;With &lt;code&gt;GitHub Copilot&lt;/code&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It's best to have two tabs open simultaneously—one for File A and one for File B—to provide the model with the correct context (which might mean closing all other tabs first).&lt;/li&gt;
&lt;li&gt;Switch to File B and write the functions I need. (If lucky, Copilot might guess what I want and autocomplete them for me.)&lt;/li&gt;
&lt;li&gt;I return to File A and import the functions from File B.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If your Copilot behaves like mine, it’s probably most helpful in step 3, when it knows which functions you are trying to use. When I am editing File B, it is harder for Copilot to infer what I want to write based on File A.&lt;/p&gt;

&lt;p&gt;Additionally, this disrupts my work in File A. Can it be made even smoother?&lt;/p&gt;

&lt;h3&gt;
  
  
  How Co Is Different
&lt;/h3&gt;

&lt;p&gt;I imagined a different kind of Copilot: one that doesn't just autocomplete within a single file but also understands your intent and writes the files you need in your workspace—almost like having two engineers working on the same project simultaneously.&lt;/p&gt;

&lt;p&gt;That’s what &lt;code&gt;Co&lt;/code&gt; does. With &lt;code&gt;Co&lt;/code&gt;, the workflow becomes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In File A, reference the function I want from File B.&lt;/li&gt;
&lt;li&gt;Save the file.&lt;/li&gt;
&lt;li&gt;If necessary, modify File B.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;Co&lt;/code&gt; will automatically generate the module you need and create an appropriate interface based on how you use the function in File A.&lt;/p&gt;

&lt;p&gt;The advantage of this approach is that you don’t need to describe what you want in natural language. Describing a feature in natural language can be more cumbersome than just writing a piece of code to demonstrate it—LLMs seem to work the same way. Using natural language forces us to translate abstract code concepts into descriptive sentences, which every software engineer knows can be frustrating.&lt;/p&gt;

&lt;p&gt;This method may aligns more closely with how LLMs excel at autocomplete.&lt;/p&gt;

&lt;p&gt;Of course, this isn’t meant to replace Copilot. Copilot's autocomplete is great, and its ability to generate documentation or refactor code is also useful. &lt;code&gt;Co&lt;/code&gt; simply complements Copilot by addressing one of its limitations (in my opinion).&lt;/p&gt;

&lt;h3&gt;
  
  
  How Does Co Work?
&lt;/h3&gt;

&lt;p&gt;From an AI perspective, it uses a simple prompt and makes a single request—no agent-based techniques are involved.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;We have "source files" reference a file not been written, I need you write the "referenced file" contents which fulfill the usage requirements in other source files. You must only return file content without any word.

${sourceFileContents}

---referenced file---
filename: ${this.path}
content:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Use Cases and Potential of Co
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Prototyping
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;Co&lt;/code&gt; is great for quickly generating module interfaces while keeping you in your workflow. Of course, the generated code won’t be perfect—it will still require some manual refinement. An ideal workflow might look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gt"&gt;&amp;gt; Edit Module A  &lt;/span&gt;
&lt;span class="gt"&gt;&amp;gt; Import module B in A and use it as if it’s already implemented.  &lt;/span&gt;
&lt;span class="gt"&gt;&amp;gt; Complete Module A.  &lt;/span&gt;
&lt;span class="gt"&gt;&amp;gt; Edit Module B.  &lt;/span&gt;
&lt;span class="gt"&gt;&amp;gt; Import module C in B and use it as if it’s already implemented.  &lt;/span&gt;
&lt;span class="gt"&gt;&amp;gt; Complete Module B.  &lt;/span&gt;
&lt;span class="gt"&gt;&amp;gt; Edit Module C.  &lt;/span&gt;
&lt;span class="gt"&gt;&amp;gt; ....  &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  TDD (Test-Driven Development)
&lt;/h4&gt;

&lt;p&gt;This workflow is actually quite similar to &lt;strong&gt;TDD&lt;/strong&gt;: define how something should be used before implementing it.&lt;/p&gt;

&lt;p&gt;With &lt;code&gt;Co&lt;/code&gt;, you can generate interface modules while writing test cases. When combined with &lt;code&gt;Copilot&lt;/code&gt;, this approach can be even more powerful.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ai</category>
      <category>githubcopilot</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Handling input file in Vue</title>
      <dc:creator>shunnNet</dc:creator>
      <pubDate>Sun, 17 Mar 2024 10:16:12 +0000</pubDate>
      <link>https://forem.com/shunnnet/handle-input-file-in-vue-51je</link>
      <guid>https://forem.com/shunnnet/handle-input-file-in-vue-51je</guid>
      <description>&lt;p&gt;The official Vue documentation does not explicitly mention how to handle input files.&lt;/p&gt;

&lt;p&gt;If you search for "vue input file" you will find many answers like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;shallowRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;inputRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;shallowRef&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;([])&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;onChange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;files&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;files&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;clear&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;inputRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;
  &lt;span class="nx"&gt;files&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;ref=&lt;/span&gt;&lt;span class="s"&gt;"inputRef"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"file"&lt;/span&gt; &lt;span class="na"&gt;multiple&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;change=&lt;/span&gt;&lt;span class="s"&gt;"onChange"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"clear"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Clear&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because you cannot directly set the value of the input file, you cannot use &lt;code&gt;v-model&lt;/code&gt; too.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;.files&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;In addition to &lt;code&gt;inputFile.value&lt;/code&gt;, you can also use &lt;code&gt;inputFile.files&lt;/code&gt; to access the value of the input file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;inputFile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;files&lt;/span&gt; &lt;span class="c1"&gt;// FileList&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;.value&lt;/code&gt; is almost read-only (can only be programmatically reset). But &lt;code&gt;.files&lt;/code&gt; can be set using &lt;code&gt;FileList&lt;/code&gt;. You can assign it a &lt;code&gt;FileList&lt;/code&gt; object. For example, you can place the files from inputFile1 into inputFile2's files.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;inputFile1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;files&lt;/span&gt;

&lt;span class="nx"&gt;inputFile2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;files&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In other words, we can set value of input file using javascript.&lt;/p&gt;

&lt;h2&gt;
  
  
  v-bind dom properties
&lt;/h2&gt;

&lt;p&gt;This feature of Vue might be a bit obscure? Because even after playing with Vue for several years, it's my first time encountering this functionality, and I've found that it's been supported since &lt;code&gt;Vue 2&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The &lt;code&gt;v-bind&lt;/code&gt; syntax supports setting DOM properties.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In Vue 3, when you use &lt;code&gt;v-bind&lt;/code&gt; on an HTML tag and the attribute is not a standard HTML attribute, Vue will use the &lt;code&gt;in&lt;/code&gt; operator to determine if it's a property of the DOM element. You can check &lt;a href="https://vuejs.org/api/built-in-directives.html#v-bind"&gt;v-bind document&lt;/a&gt;。&lt;/p&gt;

&lt;p&gt;Combining with the feature of &lt;code&gt;.files&lt;/code&gt; property, we can make a more controllable input file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;shallowRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;onChange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;files&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;files&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;clear&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;files&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;DataTransfer&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;files&lt;/span&gt; &lt;span class="c1"&gt;// fill in a empty FileList&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; 
    &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"file"&lt;/span&gt; 
    &lt;span class="na"&gt;multiple&lt;/span&gt; 
    &lt;span class="na"&gt;:files=&lt;/span&gt;&lt;span class="s"&gt;"files"&lt;/span&gt; 
    &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;change=&lt;/span&gt;&lt;span class="s"&gt;"onChange"&lt;/span&gt; 
  &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"clear"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Clear&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can check live example here: &lt;a href="https://stackblitz.com/edit/vitejs-vite-n16j6w?embed=1&amp;amp;file=src%2FApp.vue"&gt;https://stackblitz.com/edit/vitejs-vite-n16j6w?embed=1&amp;amp;file=src%2FApp.vue&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Reference
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://vuejs.org/api/built-in-directives.html#v-bind"&gt;v-bind&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer"&gt;DataTransfer&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>vue</category>
      <category>dom</category>
      <category>javascript</category>
    </item>
    <item>
      <title>給前端的簡單 AI 教學 - 2.4 prompt 總結與雜談</title>
      <dc:creator>shunnNet</dc:creator>
      <pubDate>Fri, 05 Jan 2024 16:44:03 +0000</pubDate>
      <link>https://forem.com/shunnnet/gei-qian-duan-de-jian-dan-ai-jiao-xue-24-prompt-zong-jie-yu-za-tan-5hih</link>
      <guid>https://forem.com/shunnnet/gei-qian-duan-de-jian-dan-ai-jiao-xue-24-prompt-zong-jie-yu-za-tan-5hih</guid>
      <description>&lt;p&gt;在前幾篇中有看到一些 prompt，這篇算是一個整理。不會有實作的部分。然後，由於我本身並不是機器學習專家，所以以下文章的內容算是一些非專業的經驗談。嗯好，要開始了。&lt;/p&gt;

&lt;h2&gt;
  
  
  1. 理解 prompt
&lt;/h2&gt;

&lt;p&gt;首先先來回顧一下，前幾篇在呼叫 OpenAI GPT 的時候，我們都會送一個 payload 給他，大概是長這樣的：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;role&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;system&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;content&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;你是一個客服人員，心情不太好，但是又必須保持專業的跟客人說話。&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;role&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;content&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;你們的 APP 怎麼不能用？&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;role&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;assistant&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;content&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;請問是哪裡不能用呢？&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;role&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;content&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;就卡住了啊&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;我一開始只有用過 OpenAI GPT 的語言模型，直到後來我接觸到其他語言模型，發現他們沒有地方給我輸入上面那種 JSON payload，反而告訴我，如果要實現對話功能，請使用以下的範例：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;你是一個客服人員，心情不太好，但是又必須保持專業的跟客人說話。

user: 你們的 APP 怎麼不能用？
assistant: 請問是哪裡不能用呢？
user: 就卡住了啊
assistant: 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;然後模型就會回應 assistant 會說的話：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;啊是不會說清楚喔！？
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  1.1 為什麼叫 &lt;code&gt;completion&lt;/code&gt; ?
&lt;/h2&gt;

&lt;p&gt;可能你曾經注意到，OpenAI GPT 的 API 路徑叫做 &lt;code&gt;chat/completion&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;completion&lt;/code&gt; 就是完成的意思，補完、補全、填補之類的概念。以上面那段對話來說，GPT 的行為其實就是「完成」那個對話，他會把對話變「完整」，因為那邊有個看起來很像空格的東西嘛，所以他會把他填滿。&lt;/p&gt;

&lt;p&gt;嘗試舉個例子多說明一點那種「感覺」&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;鋼Ｏ人
ＯＯ的芙莉蓮
進Ｘ的巨人
全Ｏ便利Ｘ店
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;不知道你是否在看到這些字的時候，自動把他們「完成」了？&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;鋼鐵人
葬送的芙莉蓮
進擊的巨人
全家便利商店
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;可能在看到最上面的對話的時候，就會有自己幫客服人員接話的念頭。&lt;/p&gt;

&lt;p&gt;個人見解：所以這個 api 叫做 &lt;code&gt;completion&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;而我們要做的事情，就是提供這種給他做出 &lt;code&gt;completion&lt;/code&gt; 的素材。&lt;/p&gt;

&lt;p&gt;因此，當 GPT 看到這樣的對話內容，實際上他會做的，就是根據前面的模式，將對話「接下去」：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;你是一個客服人員，心情不太好，但是又必須保持專業的跟客人說話。

user: 你們的 APP 怎麼不能用？
assistant: 請問是哪裡不能用呢？
user: 就卡住了啊
assistant: 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;是不會重新開機喔！
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  1.2 再深入一點：文字接龍
&lt;/h2&gt;

&lt;p&gt;我聽過一個說法，我認為挺貼切的：「ChatGPT 是一種超大的文字接龍機」。&lt;/p&gt;

&lt;p&gt;OpenAI GPT 這種類型的模型生成內容的時候，會根據輸入，生成下一個可能的字 （很像接龍）。&lt;/p&gt;

&lt;p&gt;你可以嘗試把以下文字任意的接下去，體會一下他的感覺：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;我
今天
早
上
忘記帶



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;他生成的時候都會像這樣一次 1 個字或是 2 個字，然後在生成完一個字比如「我」之後，去猜下一個字，比如「今天」，然後再根據前面的結果，生成下一個字。&lt;/p&gt;

&lt;p&gt;這就是為什麼說他在接龍，他實際上做的事情就是推測下一個可能的內容，然後把他生出來。&lt;/p&gt;

&lt;p&gt;那他是根據什麼去推測下一個可能是什麼字呢？嗯，就是根據他的「學習」，或者說「經驗」。&lt;/p&gt;

&lt;p&gt;他的學習資料就是海量的人類說過的話，所以某個字，某個句子，如果人常常會在這種句子說出類似的描述的話，那他也會容易說出那種話，因為人常常這樣說，他也很常看到，所以他就會根據這個推測下一個最可能的內容。&lt;/p&gt;

&lt;p&gt;你可以嘗試想想看，當你看到「我」「今天」「早」「上」「忘記帶」的時候，你直覺想到的下一個字是什麼？然後我們再嘗試換個內容「我」「昨天」「晚」「上」「忘記帶」，你直覺想到的下一個字是什麼？會不會因為一點情境跟文字差異，再加上一點點你的個人經驗，而出現不同的句子？&lt;/p&gt;

&lt;p&gt;這說不定就是 ChatGPT 的「感覺」。&lt;/p&gt;

&lt;h2&gt;
  
  
  1.3 什麼是 &lt;code&gt;systemMessage&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;好像有點扯遠了，回來看一下一開始的範例，根據原本 OpenAI GPT 的 payload，可以對照如下&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;你是一個客服人員，心情不太好，但是又必須保持專業的跟客人說話。
// systemMessage

user: 你們的 APP 怎麼不能用？ // userMessage
assistant: 請問是哪裡不能用呢？ // aiMessage
user: 就卡住了啊 // userMessage
assistant: 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;systemMessage&lt;/code&gt; 是一種「指示」(Instruction)，他會告訴 GPT 應該如何處理以下的文本。&lt;/p&gt;

&lt;p&gt;對了，前面的文章也提過，&lt;code&gt;userMessage&lt;/code&gt; 也具有類似的效果：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;user: 你是一個客服人員，心情不太好，但是又必須保持專業的跟客人說話。
assistant: 好的，請問有什麼可以協助？ 
user: 你們的 APP 怎麼不能用？
assistant: 是哪裡不能用？
user: 就卡住了啊 
assistant: 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;既然有類似效果，那這兩者有什麼不同呢？&lt;/p&gt;

&lt;p&gt;你可以把他想成一個去面試的感覺。比方說你今天去面試，然後面試前負責接待的人跟你說了一些注意事項，然後面試開始了，你按照前面的注意事項跟面試官對話：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// systemMessage
等一下會進行面試，請你先做自我介紹，約一分鐘，如果有作品的話，可以在自我介紹完展示作品。接著然後面試官會問你問題：

面試官：你好，請開始。 // userMessage
你： 你好，我是XXX，先前曾經...... // aiMessage

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;然後面試官同樣也可以給你一些指示，比方說，就在你自我介紹完，面試官可能就脫離前面說的流程，請你先做別的：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// systemMessage
等一下會進行面試，請你先做自我介紹，約一分鐘，如果有作品的話，可以在自我介紹完展示作品。接著然後面試官會問你問題：

面試官：你好，請開始。 // userMessage
你： 你好，我是XXX，先前曾經...... // aiMessage
面試官：在作品介紹之前，想先請你回答幾個問題...你剛剛說...
你：我xxxxxxx
面試官：那你有什麼什麼嗎？
......

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;雖然有個接待人員跟你說過的注意事項，但實際上，情境可能發生變化，比方說面試官對你提出注意事項以外的要求，這時候你也會拋棄前面注意事項的規則，並且以面試官說的話為主。&lt;/p&gt;

&lt;p&gt;套回去的話可以說是 userMessage 的重要性比 systemMessage 還要高。而兩個都是指示，但一個是「基本上的要求、前提、原則」，另一個是「對話對象提出來的要求」。&lt;/p&gt;

&lt;p&gt;實際上，根據模型訓練的方式，也有可能 &lt;code&gt;systemMessage&lt;/code&gt; 的重要性會比 &lt;code&gt;userMessage&lt;/code&gt; 高。想想看，在生活之中，也不一定對話的人說什麼你就做什麼吧？&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;（旁白）你是一個警察，看過太多種狡猾的犯人，你的原則就是不輕易相信別人的說詞。

我：你要相信我
你：
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;所以，&lt;code&gt;systemMessage&lt;/code&gt; 與 &lt;code&gt;userMessage&lt;/code&gt; 有何不同？這兩個東西的語義不太一樣，一個是類似旁白、畫外音的一種原則或是指示，一個對話之中對方跟你說的話。&lt;/p&gt;

&lt;h2&gt;
  
  
  2. 填鴨式教育
&lt;/h2&gt;

&lt;p&gt;是這樣的，在還是學生的時候，你可能遇到各種填鴨式教育的題型，我覺得非常適合拿來當作架構 prompt 的一些參考，尤其在訣竅上也幾乎一模一樣&lt;/p&gt;

&lt;h3&gt;
  
  
  2.1 題型
&lt;/h3&gt;

&lt;h4&gt;
  
  
  2.1.1 選擇題
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;小明跟小華到文具店買筆，小明買了 1 隻藍筆，小華買了 1 隻紅筆。一隻藍筆 20 元，一隻紅筆 10 元。請問小明和小華總共花了多少錢？

A. 50
B. 30
C. 10
D. 以上皆非

請以 A, B, C 或 D 回答，
例如：A
例如：C

答案：
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  2.1.2 是非題
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;一隻藍筆 20 元，一隻紅筆 10 元。請問「藍筆比紅筆貴」這句話是對還是錯？請回答「對」或「錯」。

答：
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  2.1.3 填空題
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;請填入對話中以（）省略的文字。請絕對只回答省略的文字，除此之外不要有其他文字。

小華：我的（）勒？
小明：誰知道
小華：是不是你吃掉了

答案：
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  2.1.4 閱讀題
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;請先閱讀以下文章，並且根據文章，回答問題。

（文章）

問題：請問女主角到底喜不喜歡男主角？
答案：

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  2.1.5 簡答題
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;小明跟小華一起到菜市場吃牛肉麵，小華沒有帶錢，小明也沒有帶錢，但是他們最後還是吃到牛肉麵了。請試圖說明小明和小華為什麼可以吃到牛肉麵（限 100 字）：
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2.2 寫 prompt 的注意事項
&lt;/h3&gt;

&lt;p&gt;我們在上面看到了一些熟悉的題型，這裡試圖從上面的例子中，說明一下常見的寫 prompt 方法：&lt;/p&gt;

&lt;h4&gt;
  
  
  2.2.1 說明清楚，越龜毛越好
&lt;/h4&gt;

&lt;p&gt;首先要盡可能的把問題描述清楚。這是說，你要盡可能地想別人可能會怎麼誤會你。&lt;/p&gt;

&lt;p&gt;我自己在寫 prompt 的時候，有時候就會遇到「自己預期的回應」跟「GPT 的回應」有微妙的誤差。這時候你就可以回去看自己的 prompt 了，似乎有些地方的描述可以再更具體一點。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;小明跟小華一起到菜市場吃牛肉麵，小華沒有帶錢，小明也沒有帶錢，但是他們最後還是吃到牛肉麵了，而且他們沒有使用錢。
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;透過增加「而且他們沒有使用錢」這句話，更限定了 GPT 的答題方向。&lt;/p&gt;

&lt;p&gt;當然，「具體」跟「細節」是可以一直填補下去的，基本上只要填補到他的回應幾乎都 OK 就行了&lt;/p&gt;

&lt;h4&gt;
  
  
  2.2.2 指定格式
&lt;/h4&gt;

&lt;p&gt;指定格式是 GPT 跟我們很有差別的部分。&lt;/p&gt;

&lt;p&gt;比方說「是非題」或是「選擇題」。如果我沒特別指定格式，實際上他可能會先說一大串，然後再說答案「是」。&lt;/p&gt;

&lt;p&gt;因為我們已經很熟悉這種問題應該要怎麼回應了，所以我們可以用最簡短、格式化的方式回應（我們被調教得很好）。&lt;/p&gt;

&lt;p&gt;但是 GPT，他是個孩子呀～你最好明確的告訴他怎麼回，最好還要加個例子，因為「範例」很具體，「範例」是一個可以模仿的東西&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.....

請只以 A, B, C 或 D 回答，
回答範例一：A
回答範例二：C

回答：
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  2.2.3 回答：
&lt;/h4&gt;

&lt;p&gt;注意一下，這邊有個「回答：」。為什麼要有這個呢？假設我們把他抽掉，以他 &lt;code&gt;completion&lt;/code&gt; 的天性來看，他說不定會試圖去「讓這個題目變得完整」，換句話說我給了他誤會的空間，導致他可能會回答：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.....
回答範例一：A
回答範例二：C

回答範例三：B
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;因此為了明確告訴他，「這個題目已經結束，接下來是回答」，所以我加了「回答：」&lt;/p&gt;

&lt;h3&gt;
  
  
  2.3 他真的知道自己在說什麼嗎？
&lt;/h3&gt;

&lt;p&gt;有一次我嘗試透過 ChatGPT 學習 GCP 的網路架構，剛開始我有種終於找到個說人話的了，很安心。然後當我針對某些概念追問，或是嘗試比較類似的A 或 B，兩者有什麼差異的時候，我發現他會明顯地說出前後矛盾，或是沒有明顯差異的描述，然後說「因此這兩個是不一樣的」。&lt;/p&gt;

&lt;p&gt;這大概就是一種時常會說到，LLM 會有的「幻覺」問題&lt;/p&gt;

&lt;p&gt;結合前面提到的，GPT 的基本行為是「根據他看過的文本，推測下一個最有可能的字」。而他推測的素材是他學習到的「人類的說話模式」。簡單來說，他只是在模仿人類說話。或者說他的就是在掰。&lt;/p&gt;

&lt;p&gt;不過他還是有可以做到一定的邏輯推論，而且可以用 prompt 強化邏輯推理的效果。只是如果高度要求準確，使用上要小心。因為它就像是一個只是會講出很多了不起的名詞，可是完全不明白那些是什麼意思的屁孩。&lt;/p&gt;

&lt;h3&gt;
  
  
  3. 結尾
&lt;/h3&gt;

&lt;p&gt;最後要說一下，每一家出的模型的訓練方式並不相同，什麼樣的 Prompt 會確實有效，真的是要嘗試過後才知道。但是文章內說的一些概念仍然可以參考與應用。&lt;/p&gt;

&lt;p&gt;下一篇文章，會介紹 LangChain 與 LangChain Agent。一提到 Agent 會以為是什麼很複雜的東西，但其實他只是個 Prompt 技巧。下一篇會來介紹這種特別的 prompt。&lt;/p&gt;

&lt;p&gt;然後推薦想多認識 prompt 跟一些技巧的人參考以下網站：&lt;/p&gt;

&lt;h4&gt;
  
  
  OpenAI: Prompt Engineering
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://platform.openai.com/docs/guides/prompt-engineering/six-strategies-for-getting-better-results"&gt;https://platform.openai.com/docs/guides/prompt-engineering/six-strategies-for-getting-better-results&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;這個是 OpenAI 自己出的 prompt 撰寫指南，推薦去讀一下&lt;/p&gt;

&lt;h4&gt;
  
  
  Prompt Engineering
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://www.promptingguide.ai/techniques/zeroshot"&gt;https://www.promptingguide.ai/techniques/zeroshot&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;這個網站介紹了很多 prompt 的技巧，雖然有一些對 OpenAI GPT 沒有什麼效果（因為他已經很強大了）。但當你遇到瓶頸，怎麼樣也無法讓他好好回應時，你可以回來這裡找靈感。&lt;/p&gt;

&lt;h4&gt;
  
  
  Google: Prompt design strategies
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://ai.google.dev/docs/prompt_best_practices?hl=en#prompt-iteration-strategies"&gt;https://ai.google.dev/docs/prompt_best_practices?hl=en#prompt-iteration-strategies&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;如果你想換換口味，Google 的 prompt 文件也說了不少東西。甚至你可以去試試 Gemini 模型。&lt;/p&gt;




&lt;h2&gt;
  
  
  Try Browser AI Project (In development)
&lt;/h2&gt;

&lt;p&gt;Use Browser AI to help you build an LLM powered website!&lt;/p&gt;

&lt;p&gt;Repository: &lt;a href="https://github.com/shunnNet/browser-ai"&gt;https://github.com/shunnNet/browser-ai&lt;/a&gt;&lt;br&gt;
Website: &lt;a href="https://courageous-manatee-a625e9.netlify.app/"&gt;https://courageous-manatee-a625e9.netlify.app/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>frontend</category>
      <category>openai</category>
    </item>
    <item>
      <title>給前端的簡單 AI 教學 - 2.3 在 llm 回應中渲染 custom component</title>
      <dc:creator>shunnNet</dc:creator>
      <pubDate>Sun, 31 Dec 2023 10:17:22 +0000</pubDate>
      <link>https://forem.com/shunnnet/gei-qian-duan-de-jian-dan-ai-jiao-xue-23-zai-llm-hui-ying-zhong-xuan-ran-custom-component-1ii6</link>
      <guid>https://forem.com/shunnnet/gei-qian-duan-de-jian-dan-ai-jiao-xue-23-zai-llm-hui-ying-zhong-xuan-ran-custom-component-1ii6</guid>
      <description>&lt;p&gt;如果你曾經跟 ChatGPT 聊過天，會發現他的回應中不只有文字，還有列表、 &lt;code&gt;&amp;lt;code&amp;gt;&lt;/code&gt; 區塊，甚至有可能會顯示個圖片給你看...&lt;/p&gt;

&lt;p&gt;因為 OpenAI API 在回應的時候會預設回應 &lt;code&gt;markdown&lt;/code&gt; 格式，如果 LLM 不是預設回應 markdown，你也可以使用 prompt，請他以 markdown 格式回應。&lt;/p&gt;

&lt;p&gt;只要他是以 markdown 回應，我們就可以利用渲染 markdown 的元件客製化顯示內容。比如使用 &lt;a href="https://github.com/remarkjs/react-markdown"&gt;&lt;code&gt;react-markdown&lt;/code&gt;&lt;/a&gt; 或是使用 &lt;a href="https://github.com/shunnNet/vue-markdown"&gt;&lt;code&gt;vue-markdown&lt;/code&gt;&lt;/a&gt;。&lt;/p&gt;

&lt;p&gt;此外，我們也可以利用這兩個套件，渲染非標準 markdown 元素，比如 &lt;code&gt;ProductCard&lt;/code&gt;, &lt;code&gt;LoginForm&lt;/code&gt; 等客製化元件。&lt;/p&gt;

&lt;h2&gt;
  
  
  前置
&lt;/h2&gt;

&lt;p&gt;你可以直接查看這篇文章的完整程式碼，以節省你的時間，有 &lt;code&gt;Vue&lt;/code&gt; 跟 &lt;code&gt;React&lt;/code&gt; 兩個範例。&lt;/p&gt;

&lt;p&gt;這篇文章將以 &lt;code&gt;Vue&lt;/code&gt; 的程式碼進行解說。但應該都可以找到 &lt;code&gt;React&lt;/code&gt; 的對應寫法。&lt;/p&gt;

&lt;p&gt;你可以參照範例中的 &lt;code&gt;Readme.md&lt;/code&gt; 進行設置。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/shunnNet/browser-ai-tutorial/tree/main/04-insert-component/vue-prompt-component"&gt;Vue sample code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/shunnNet/browser-ai-tutorial/tree/main/04-insert-component/react-prompt-component"&gt;React sample code&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  1.1 配置元件
&lt;/h2&gt;

&lt;p&gt;首先我們要先設置渲染 markdown 的元件。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;vue-markdown&lt;/code&gt; 跟 &lt;code&gt;react-markdown&lt;/code&gt; 預設都只渲染最基本的 markdown，像是 &lt;code&gt;table&lt;/code&gt; 之類的元素會無法對應，所以我們需要為他們加上 &lt;code&gt;remark-gfm&lt;/code&gt; plugin。&lt;/p&gt;

&lt;p&gt;此外，為了渲染我們的客製化元件，我們需要加上渲染 &lt;code&gt;html&lt;/code&gt; 的能力，因此需要加上 &lt;code&gt;rehype-raw&lt;/code&gt;。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Vue --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;VueMarkdown&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@crazydos/vue-markdown&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;remarkGfm&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;remark-gfm&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;rehypeRaw&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rehype-raw&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;markdown&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`
  ## hello world
`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!--
    "sanitize=false" is required to allow non-standard HTML
    This is not required for "react-markdown"
  --&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;VueMarkdown&lt;/span&gt;
    &lt;span class="na"&gt;:markdown=&lt;/span&gt;&lt;span class="s"&gt;"markdown"&lt;/span&gt;
    &lt;span class="na"&gt;:remarkPlugins=&lt;/span&gt;&lt;span class="s"&gt;"[remarkGfm]"&lt;/span&gt;
    &lt;span class="na"&gt;:rehypePlugins=&lt;/span&gt;&lt;span class="s"&gt;"[rehypeRaw]"&lt;/span&gt;
    &lt;span class="na"&gt;:sanitize=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/VueMarkdown&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  1.2 客製化標準 markdown 元素
&lt;/h2&gt;

&lt;p&gt;接著，我們來試著讓他渲染客製化元件。首先是對標準 &lt;code&gt;markdown&lt;/code&gt; 進行渲染。&lt;code&gt;VueMarkdown&lt;/code&gt; 的情況是，你可以透過 &lt;code&gt;scoped-slot&lt;/code&gt; 客製化 html 元素。在 &lt;code&gt;react-markdown&lt;/code&gt; 中你也可以找到對應的功能。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;VueMarkdown&lt;/span&gt;
    &lt;span class="na"&gt;:markdown=&lt;/span&gt;&lt;span class="s"&gt;"markdown"&lt;/span&gt;
    &lt;span class="na"&gt;:remarkPlugins=&lt;/span&gt;&lt;span class="s"&gt;"[remarkGfm]"&lt;/span&gt;
    &lt;span class="na"&gt;:rehypePlugins=&lt;/span&gt;&lt;span class="s"&gt;"[rehypeRaw]"&lt;/span&gt;
    &lt;span class="na"&gt;:sanitize=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;template&lt;/span&gt; &lt;span class="na"&gt;#h2&lt;/span&gt;&lt;span class="err"&gt;="&lt;/span&gt;{ children }"&amp;gt;
      &lt;span class="nt"&gt;&amp;lt;h2&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text-red text-underline"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;Component&lt;/span&gt; &lt;span class="na"&gt;:is=&lt;/span&gt;&lt;span class="s"&gt;"children"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/VueMarkdown&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  1.3 渲染客製化元件
&lt;/h2&gt;

&lt;p&gt;比如說你可能會有個元件 &lt;code&gt;&amp;lt;LoginForm&amp;gt;&lt;/code&gt;，你想要在 markdown 內容中穿插他，以 &lt;code&gt;VueMarkdown&lt;/code&gt; 的做法是使用 &lt;code&gt;&amp;lt;slot slot-name="slotName"&amp;gt;&amp;lt;/slot&amp;gt;&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Vue --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;RecommendProducts&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./components/RecommendProducts.vue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;markdown&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`
  ## Hello world

  &amp;lt;slot slot-name="recommend-products"&amp;gt;&amp;lt;/slot&amp;gt;

  I am another content ....
`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!--
    "sanitize=false" is required to allow non-standard HTML
    This is not required for "react-markdown"
  --&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;VueMarkdown&lt;/span&gt;
    &lt;span class="na"&gt;:markdown=&lt;/span&gt;&lt;span class="s"&gt;"markdown"&lt;/span&gt;
    &lt;span class="na"&gt;:remarkPlugins=&lt;/span&gt;&lt;span class="s"&gt;"[remarkGfm]"&lt;/span&gt;
    &lt;span class="na"&gt;:rehypePlugins=&lt;/span&gt;&lt;span class="s"&gt;"[rehypeRaw]"&lt;/span&gt;
    &lt;span class="na"&gt;:sanitize=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!-- omitted... --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;template&lt;/span&gt; &lt;span class="na"&gt;#recommend-products&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;RecommendProducts&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/VueMarkdown&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;這麼一來渲染的準備就差不多了。我們來看看要怎麼處理 GPT 。&lt;/p&gt;

&lt;h2&gt;
  
  
  2.1 Prompt - 請插入特定的語法
&lt;/h2&gt;

&lt;p&gt;在這篇中，我會使用 &lt;code&gt;systemMessage&lt;/code&gt; 告訴 OpenAI GPT 如何進行回應。&lt;/p&gt;

&lt;p&gt;若你是從前面看過來的人，或許你會對我一下使用 &lt;code&gt;systemMessage&lt;/code&gt; 一下使用 &lt;code&gt;userMessage&lt;/code&gt; 給 LLM 指示感到困惑。我會在下一篇文章說明這兩者的不同。我會在這裡使用 &lt;code&gt;systemMessage&lt;/code&gt;，是因為&lt;strong&gt;我認為語意上比較順&lt;/strong&gt;。&lt;/p&gt;

&lt;p&gt;這裡的主要概念是，要求 GPT 插入特定的字串到他的回應中：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;system&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Answer in markdown format. I will provide you some syntax and its usage, you may insert the syntax into appropriate position in your answer when it may help user without any modification to syntax.`&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;然後還需要跟他說要插入的語法：前面我們有提到，是使用 &lt;code&gt;&amp;lt;slot slot-name="slot-name"&amp;gt;&amp;lt;/slot&amp;gt;&lt;/code&gt; 這樣的語法。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;system&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Answer in markdown format. I will provide you some syntax and its usage, you may insert the syntax into appropriate position in your answer when it may help user without any modification to syntax.

syntax (recommend-products): &amp;lt;slot slot-name="recommend-products"&amp;gt;&amp;lt;/slot&amp;gt;
syntax description (recommend-products): A list of recommended products
`&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;前幾篇文章中有提到使用這樣的 prompt 描述一些 item 的做法，他讓 LLM 可以從中挑選適合的 item：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;---Element: recommend-products---
id: recommend-products
description: A list of recommended products

---Element: login-form---
id: login-form
description: A form to login to the service, user need to input email and password, or use social login e.g: Google, Facebook, Twitter, etc.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;其實只要他是遵照一個固定、明顯的格式，通常 LLM 都可以辨識出來那是一個區塊。因此在這裡我也可以將格式寫成以下：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;system&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Answer in markdown format. I will provide you some syntax and its usage, you may insert the syntax into appropriate position in your answer when it may help user without any modification to syntax.

syntax (recommend-products): &amp;lt;slot slot-name="recommend-products"&amp;gt;&amp;lt;/slot&amp;gt;
syntax description (recommend-products): A list of recommended products

syntax (login-form): &amp;lt;slot slot-name="login-form"&amp;gt;&amp;lt;/slot&amp;gt;
syntax description (login-form): A form to login to the service, user need to input email and password, or use social login e.g: Google, Facebook, Twitter, etc.
`&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;注意，在這裡我提示 LLM 的是：&lt;code&gt;請插入你認為可能可以幫助使用者的語法&lt;/code&gt;，因此他不一定會把兩個語法都插入到他的回應。我用的是 &lt;code&gt;you may insert&lt;/code&gt;，如果強烈要求他一定要插入，你也可以改成 &lt;code&gt;you must insert&lt;/code&gt;。&lt;/p&gt;

&lt;h2&gt;
  
  
  2.2 Prompt - 加入脈絡、加入範例
&lt;/h2&gt;

&lt;p&gt;我在寫這個範例的時候遇到一些問題&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;他有可能以為這是一個語法教學的對話&lt;/li&gt;
&lt;li&gt;他有可能以 markdown 程式碼區塊的方式插入語法&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;來看一下怎麼解決這兩個問題：&lt;/p&gt;

&lt;h3&gt;
  
  
  2.2.1 Prompt - 加入脈絡
&lt;/h3&gt;

&lt;p&gt;我預設的情境是：這是一個客服跟客人的對話。但是他可能會這樣回應：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You can insert the following syntax to login:

&amp;lt;slot slot-name="login-form"&amp;gt;&amp;lt;/slot&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;總不能讓客人看見這種東西吧 orz。&lt;/p&gt;

&lt;p&gt;他會說出這種話，是因為我們沒有給他明確的情境限制，如果沒有告訴他，他通常都會自己猜，而那可能不是我們要的。因此我們可以明確的告訴他，這是什麼對話，或者他的身份。比如，你是一個客服人員。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nl"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;system&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`You are a customer service. Please help user to solve their problem.

...`&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2.2.2 Prompt - 加入範例：One Shot
&lt;/h3&gt;

&lt;p&gt;第二個問題：他有可能以 markdown 程式碼區塊的方式插入語法。&lt;/p&gt;

&lt;p&gt;比如他可能會這樣回應：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;'''html
&amp;lt;slot slot-name="login-form"&amp;gt;&amp;lt;/slot&amp;gt;
'''
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;不管是 &lt;code&gt;react-markdown&lt;/code&gt; 或是 &lt;code&gt;vue-markdown&lt;/code&gt; 都會將這裡渲染成 &lt;code&gt;&amp;lt;pre&amp;gt;&amp;lt;code&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&lt;/code&gt;，而不是把它解析成 &lt;code&gt;html&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;為了提高他成功插入的機率，我們給他加入一個插入的範例：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;example: 
user: I want to buy a product
you: ...part of your answer... &amp;lt;slot slot-name="recommend-products"&amp;gt;&amp;lt;/slot&amp;gt; ...part of your answer...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;像這種丟一個範例給他的做法，是一種叫做 one-shot 的 prompt 方法。當你發現 LLM 的回應不是很理想，或是總是沒有照著你的格式跑的時候，你可以丟一個範例讓他「照著做」。是一種「像是這種感覺的回應我」的東西。&lt;/p&gt;

&lt;p&gt;舉一個例：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Please categorize the following items with possitive, negative:

rainy day // negative
sunny day // 

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;回答通常會是&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;positive
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;你可以到 &lt;code&gt;ChatGPT&lt;/code&gt; 去試試有加跟沒加的效果。比如以下這個 prompt，你會發現他的回應比較自由奔放：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Please categorize the following items with possitive, negative:

rainy day // 

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2.3 Prompt - 完整的 Prompt
&lt;/h3&gt;

&lt;p&gt;綜合以上，Prompt 會長得像是這樣。我們在這之後加入 &lt;code&gt;userMessage&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userMessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;....&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;system&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`You are a customer service. Please help user to solve their problem.
Answer in markdown format. I will provide you some syntax and its usage, you may insert the syntax into appropriate position in your answer when it may help user without any modification to syntax.

example: 
user: I want to buy a product
you: ...part of your answer : &amp;lt;slot slot-name="recommend-products"&amp;gt;&amp;lt;/slot&amp;gt; ...part of your answer...

syntax (recommend-products): &amp;lt;slot slot-name="recommend-products"&amp;gt;&amp;lt;/slot&amp;gt;
syntax description (recommend-products): A list of recommended products

syntax (login-form): &amp;lt;slot slot-name="login-form"&amp;gt;&amp;lt;/slot&amp;gt;
syntax description (login-form): A form to login to the service, user need to input email and password, or use social login e.g: Google, Facebook, Twitter, etc.
`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userMessage&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. Try it
&lt;/h2&gt;

&lt;p&gt;接著我們就可以嘗試對他輸入一些訊息了，看他會不會根據情況渲染出元件。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Show me some products
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;結果是：&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nK_2qqcu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nycw5lvq7xvn5t6qswcw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nK_2qqcu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nycw5lvq7xvn5t6qswcw.png" alt="render-component-in-llm-message" width="800" height="786"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;由於篇幅的關係，沒有呈現出完整的程式碼，如最開始所說的，你可以到以下地方查看完整的實作範例：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/shunnNet/browser-ai-tutorial/tree/main/04-insert-component/vue-prompt-component"&gt;Vue sample code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/shunnNet/browser-ai-tutorial/tree/main/04-insert-component/react-prompt-component"&gt;React sample code&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;若是你遇到一些問題也歡迎在下方留言。&lt;/p&gt;

&lt;p&gt;若你是 &lt;code&gt;Vue&lt;/code&gt; 的使用者，你也可以參考看看這個套件的範例 &lt;a href="https://github.com/shunnNet/vue-llm-rich-message"&gt;&lt;code&gt;vue-llm-rich-message&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;在下一篇文章，將會說明一些 prompt 的概念，或許可以幫助你更彈性的運用 prompt。&lt;/p&gt;

&lt;h2&gt;
  
  
  Reference
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://platform.openai.com/docs/guides/prompt-engineering/tactic-provide-examples"&gt;&lt;code&gt;OpenAI Documentation: One-Shot&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/remarkjs/react-markdown"&gt;&lt;code&gt;react-markdown&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/shunnNet/vue-markdown"&gt;&lt;code&gt;vue-markdown&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/shunnNet/vue-llm-rich-message"&gt;&lt;code&gt;vue-llm-rich-message&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try Browser AI Project (In development)
&lt;/h2&gt;

&lt;p&gt;Use &lt;code&gt;Browser AI&lt;/code&gt; to help you build an LLM powered website!&lt;/p&gt;

&lt;p&gt;Repository: &lt;a href="https://github.com/shunnNet/browser-ai"&gt;https://github.com/shunnNet/browser-ai&lt;/a&gt;&lt;br&gt;
Website: &lt;a href="https://courageous-manatee-a625e9.netlify.app/"&gt;https://courageous-manatee-a625e9.netlify.app/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>openai</category>
      <category>webdev</category>
      <category>frontend</category>
      <category>ai</category>
    </item>
    <item>
      <title>Simple AI Tutorial for Front-end - 1. Connecting to OpenAI</title>
      <dc:creator>shunnNet</dc:creator>
      <pubDate>Sat, 23 Dec 2023 15:18:25 +0000</pubDate>
      <link>https://forem.com/shunnnet/simple-ai-tutorial-for-front-end-1-connecting-to-openai-5ejc</link>
      <guid>https://forem.com/shunnnet/simple-ai-tutorial-for-front-end-1-connecting-to-openai-5ejc</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;This should be the first post in a series, sharing some knowledge and insights from my development of applications related to Large Language Models (LLM) over the past year. The entire series will cover the following topics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How to use &lt;code&gt;OpenAI&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Basic knowledge of using prompts&lt;/li&gt;
&lt;li&gt;Function calls&lt;/li&gt;
&lt;li&gt;Brief overview of &lt;code&gt;Langchain&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;How to make LLM respond based on company documents&lt;/li&gt;
&lt;li&gt;Integration possibilities with &lt;a href="https://courageous-manatee-a625e9.netlify.app/"&gt;Browser AI&lt;/a&gt; packages and front-end frameworks&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Theme
&lt;/h2&gt;

&lt;p&gt;This article will cover a very simple task – connecting to the OpenAI API, a process that can be completed in about 10 minutes. The following are the two main steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Obtain an API KEY&lt;/li&gt;
&lt;li&gt;Make a Request on the Webpage&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  A. Obtain OpenAI API KEY
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Register an account on OpenAI
&lt;/h3&gt;

&lt;p&gt;Visit &lt;a href="https://platform.openai.com/docs/introduction"&gt;https://platform.openai.com/docs/introduction&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the top right corner, you should see "sign up." Click on it to start the registration process.&lt;br&gt;
Follow the registration process to create your account.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CGWYpl0X--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rj244vizgzoewz2kbcox.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CGWYpl0X--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rj244vizgzoewz2kbcox.png" alt="OpenAI - sign up" width="800" height="482"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  2. Confirm Quota
&lt;/h3&gt;

&lt;p&gt;After registration, you'll be redirected to the documentation page. You can click on "settings" on the left side, then navigate to "Limits." Scroll down to the bottom, where you'll find the following text. It mentions that you are currently on a free plan, and payment will only start after reaching $5. For experimenting, this amount should be more than sufficient.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--w-IR5kfr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c9y54igfsttinxgtp8r7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--w-IR5kfr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c9y54igfsttinxgtp8r7.png" alt="OpenAI - free tier" width="800" height="377"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also click on "Usage" on the left to check your usage:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--drSKzzKF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v2vbug0jogtjjif6w0jh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--drSKzzKF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v2vbug0jogtjjif6w0jh.png" alt="OpenAI - free tier usage" width="800" height="397"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  3. Obtain API Key
&lt;/h3&gt;

&lt;p&gt;Click on "API keys" on the left side to access the page shown in the image below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TJqZbu6P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n944obnjk2fnqiabkb4r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TJqZbu6P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n944obnjk2fnqiabkb4r.png" alt="OpenAI - api key page" width="800" height="529"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To create an API key, you need to undergo phone verification. Click the button in the image below and follow the steps to proceed:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tJsMhw1v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/onuce42z5o500ziijlrw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tJsMhw1v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/onuce42z5o500ziijlrw.png" alt="OpenAI - verify phone number button" width="800" height="555"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After completing the phone verification, click on &lt;strong&gt;Create new secret key.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NmO5CDFD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0caxkituw57xkxm4drik.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NmO5CDFD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0caxkituw57xkxm4drik.png" alt="OpenAI - create new secret key button" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here, pay a little attention:&lt;/p&gt;

&lt;p&gt;First, you'll need to enter a name; just choose a simple one.&lt;br&gt;
After submitting the name, the API KEY will appear in the same pop-up. Copy the key and keep it secure, avoiding sharing it with others.&lt;br&gt;
If, by chance, you accidentally close this pop-up without copying the key, delete the existing key and create a new one.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--A9a4vZeR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8ynpg9dhsq06gylk0t1o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A9a4vZeR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8ynpg9dhsq06gylk0t1o.png" alt="OpenAI - Enter new secret key name" width="800" height="364"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jizKFpet--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/odi3fxoo8sam1jxer49l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jizKFpet--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/odi3fxoo8sam1jxer49l.png" alt="OpenAI - Copy new secret key value" width="800" height="439"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that you have the API key, you can start making API calls.&lt;/p&gt;
&lt;h2&gt;
  
  
  B. Calling the GPT on the Webpage
&lt;/h2&gt;

&lt;p&gt;After preparing the API key, let's move on to calling the most commonly used chatCompletion API.&lt;/p&gt;

&lt;p&gt;Create an HTML file and use the following code: (Remember to replace "your API key" with your actual API key in the variable)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"ask"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Ask&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;my_openai_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Paste your key here&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;chatCompletion&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://api.openai.com/v1/chat/completions&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,{&lt;/span&gt;
        &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Authorization&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Bearer &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;my_openai_key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
          &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gpt-3.5-turbo&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello ChatGPT&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;
          &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ask&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;chatCompletion&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, open this HTML file, click the "Ask" button, wait for a moment, and you should see the response below. This indicates that the connection has been successfully established.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yCoGnxO9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0hb30ajoir1o5pxjcths.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yCoGnxO9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0hb30ajoir1o5pxjcths.png" alt="Chat completion API result" width="800" height="1006"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you want to continue the conversation, copy the AI's response, add it to the "messages" array along with your message, like the example below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
     &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gpt-3.5-turbo&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="na"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
       &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello ChatGPT&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;

       &lt;span class="c1"&gt;// Put ai response here like this&lt;/span&gt;
       &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;assistant&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello, how can I assist you today?&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;

       &lt;span class="c1"&gt;// Then add user response here&lt;/span&gt;
       &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;I just want to say hi&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
     &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, click the "Ask" button again, and you'll see it responding with new content.&lt;/p&gt;




&lt;p&gt;So, this article concludes here.&lt;/p&gt;

&lt;p&gt;The next article will discuss how to make OpenAI's GPT generate the responses you desire.&lt;/p&gt;




&lt;h2&gt;
  
  
  Reference:
&lt;/h2&gt;

&lt;p&gt;Here is the specification and documentation for the chatCompletion API we just called. Feel free to explore it if you're interested.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://platform.openai.com/docs/guides/text-generation"&gt;OpenAI - Text generation&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://platform.openai.com/docs/api-reference/chat/create"&gt;OpenAI - Create chat completion&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Advertisment - Browser AI
&lt;/h2&gt;

&lt;p&gt;Use &lt;code&gt;Browser AI&lt;/code&gt; to help you build an LLM powered website!&lt;br&gt;
Repository: &lt;a href="https://github.com/shunnNet/browser-ai"&gt;https://github.com/shunnNet/browser-ai&lt;/a&gt;&lt;br&gt;
Documentation: &lt;a href="https://courageous-manatee-a625e9.netlify.app/"&gt;https://courageous-manatee-a625e9.netlify.app/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>openai</category>
      <category>frontend</category>
      <category>ai</category>
      <category>webdev</category>
    </item>
    <item>
      <title>給前端的簡單 AI 教學 - 2.2 用 LLM 選擇 DOM 元素</title>
      <dc:creator>shunnNet</dc:creator>
      <pubDate>Tue, 19 Dec 2023 15:25:00 +0000</pubDate>
      <link>https://forem.com/shunnnet/gei-qian-duan-de-jian-dan-ai-jiao-xue-22-yong-llm-xuan-ze-dom-yuan-su-25el</link>
      <guid>https://forem.com/shunnnet/gei-qian-duan-de-jian-dan-ai-jiao-xue-22-yong-llm-xuan-ze-dom-yuan-su-25el</guid>
      <description>&lt;h2&gt;
  
  
  前言
&lt;/h2&gt;

&lt;p&gt;前一篇文章提到了如何用 LLM 選擇一個單詞後，透過單詞決定要渲染的元素（或是要執行的動作）。&lt;/p&gt;

&lt;p&gt;這篇文章會再舉一個 prompt 的範例，讓 LLM 選擇一個 DOM 元素。&lt;/p&gt;

&lt;p&gt;可以到 Github 看到這篇文章的&lt;a href="https://github.com/shunnNet/browser-ai-tutorial/blob/main/03-choose-dom/index.html"&gt;完整原始碼&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CYFjQ72V--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0gug62t60wnqrutmnawn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CYFjQ72V--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0gug62t60wnqrutmnawn.png" alt="概念說明" width="800" height="535"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  寫 Prompt 的一個方法
&lt;/h2&gt;

&lt;p&gt;由於之後的文章才會多提一點 prompt 的相關知識，所以先在這裡給一個可以用來寫 prompt 的方法（個人見解）：&lt;/p&gt;

&lt;p&gt;想像你是一個國中老師，要出考題給學生(GPT)：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;題目要描述清楚&lt;/li&gt;
&lt;li&gt;多提供一點細節，避免誤會&lt;/li&gt;
&lt;li&gt;如果學生答不好，多給一點提示&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  1. 為 DOM 加上說明
&lt;/h2&gt;

&lt;p&gt;你可以沿用上次的範例，或是直接使用這次的原始碼。&lt;/p&gt;

&lt;p&gt;然後稍微在畫面加上幾個元素，&lt;code&gt;「登入」按鈕&lt;/code&gt;，&lt;code&gt;「停止訂閱」按鈕&lt;/code&gt;，跟一段&lt;code&gt;「說明文字」&lt;/code&gt;。這三個是這一次的目標。&lt;br&gt;
為了說明方便，還加上了一段 CSS。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"chat"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;textarea&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"input"&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/textarea&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Ask&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!--New part--&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
&lt;span class="nc"&gt;.highlight&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;yellow&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&amp;gt;&lt;/span&gt;Login&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&amp;gt;&lt;/span&gt;Unsubscribe&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;section&amp;gt;&lt;/span&gt;
  Lorem
  ipsum dolor sit amet consectetur adipisicing elit. Placeat, laboriosam atque esse asperiores animi facere nihil
  amet minus vel corrupti, aliquam voluptates alias delectus est sint maiores saepe quasi iure.
&lt;span class="nt"&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;接下來要對這三個元素加上一些資訊，我們分別為他們加上 ID，以及加上一段文字說明「這個元素的內容、作用」。&lt;/p&gt;

&lt;p&gt;我會使用兩個標籤 &lt;code&gt;data-ai-id&lt;/code&gt;, &lt;code&gt;data-ai-description&lt;/code&gt;。沒有規範說一定要這樣設定，所以只要可以給出相同的資訊，標籤名稱是可以任意設置的。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- 點擊之後，顯示登入彈窗 --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; 
  &lt;span class="na"&gt;data-ai-id=&lt;/span&gt;&lt;span class="s"&gt;"login-button"&lt;/span&gt;
  &lt;span class="na"&gt;data-ai-description=&lt;/span&gt;&lt;span class="s"&gt;"The button, when clicked, can open a login popup."&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  Login
&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- 點擊之後，可以終止訂閱 browser-ai --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt;
  &lt;span class="na"&gt;data-ai-id=&lt;/span&gt;&lt;span class="s"&gt;"unsubscribe-button"&lt;/span&gt;
  &lt;span class="na"&gt;data-ai-description=&lt;/span&gt;&lt;span class="s"&gt;"Clicking it will terminate users subscription of browser-ai."&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  Unsubscribe
&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- 描述如何在專案中安裝 browser-ai，是了解 browser-ai 的資訊 --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;section&lt;/span&gt; 
  &lt;span class="na"&gt;data-ai-id=&lt;/span&gt;&lt;span class="s"&gt;"usage-doc"&lt;/span&gt;
  &lt;span class="na"&gt;data-ai-description=&lt;/span&gt;&lt;span class="s"&gt;"A section describe how to install browser-ai in user's project, a good infomation to learn browser-ai"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  ...omit...
&lt;span class="nt"&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. 製作 prompt
&lt;/h2&gt;

&lt;h3&gt;
  
  
  2.1 指示
&lt;/h3&gt;

&lt;p&gt;是這樣的，這次我希望 GPT 可以做到一件事：根據使用者的訊息（或是對話），選擇一個使用者可能會感興趣的 DOM元素，並把元素 ID 傳回來給我。&lt;/p&gt;

&lt;p&gt;也就是說，&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GPT 要根據一段「內容」&lt;/li&gt;
&lt;li&gt;回答我問的「問題」：一個使用者可能會感興趣的 DOM 元素&lt;/li&gt;
&lt;li&gt;以指定「格式」回答我：DOM ID &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;組合起來就是：請閱讀內容，遵照指定的格式，回答問題&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
  &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Reading the content in "Content" section, and answer the question in "Question" section with strictly follow the instruction in "Format" section.`&lt;/span&gt;
&lt;span class="p"&gt;}]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;這邊有兩點說明一下：&lt;br&gt;
第一，這次是把指示放在 &lt;code&gt;userMessage&lt;/code&gt;。上一篇文章有提到，可以把一些回答的指示放在 &lt;code&gt;systemMessage&lt;/code&gt; 中。但同時也提到，雖然跟放在 &lt;code&gt;systemMessage&lt;/code&gt; 有些微的語意差別，但其實直接把指示放在 &lt;code&gt;userMessage&lt;/code&gt; 也可以。&lt;/p&gt;

&lt;p&gt;第二，這個 &lt;code&gt;prompt&lt;/code&gt; 還沒完，只寫了一半。&lt;/p&gt;

&lt;p&gt;在這一段 &lt;code&gt;prompt&lt;/code&gt; 中，我提示了 GPT 底下會有一些 &lt;code&gt;section&lt;/code&gt;，告訴他每一個 &lt;code&gt;section&lt;/code&gt; 的意思，以及回答問題的步驟。&lt;/p&gt;
&lt;h3&gt;
  
  
  2.2 段落
&lt;/h3&gt;

&lt;p&gt;接下來要把各個段落給他，也就是 &lt;code&gt;內容 Content&lt;/code&gt;, &lt;code&gt;問題 Question&lt;/code&gt;, &lt;code&gt;格式 Format&lt;/code&gt;，再加上一個 &lt;code&gt;回答 Answer&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
  &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Reading the content in "Content" section, and answer the question in "Question" section with strictly follow the instruction in "Format" section.

"""Content"""
user: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;userMessage&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;

"""Question"""
Which element might customers be interested in?

"""Format"""
You must answer with one of the following Element Id with no other words. If you cannot determine, just say '__no__'.

"""Answer"""

`&lt;/span&gt;
&lt;span class="p"&gt;}]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;這裡要先說明「段落」是怎麼回事。&lt;/p&gt;

&lt;p&gt;首先每個段落我都用固定的格式區分 &lt;code&gt;"""段落標題"""&lt;/code&gt;，這種固定格式的作法，可以幫助 LLM 了解這是一個區塊，或是一個段落。然後也方便對 LLM 說明每個區塊。&lt;/p&gt;

&lt;p&gt;然後，不一定要使用 &lt;code&gt;"""段落標題"""&lt;/code&gt; 這個格式。只要是一致的模式，「看起來像一個段落」就可以。比方說&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;Content&amp;gt;

&amp;lt;Question&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;或是&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;---Content---

---Question---
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;LLM 這種生物是最喜歡模式了。（我猜啦）&lt;/p&gt;

&lt;p&gt;接下來說明一下每個段落:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Content&lt;/code&gt;：因為我們希望 LLM 根據使用者的訊息回答問題，所以「內容」就是指「對話」了。所以我在這裡放了使用者輸入的訊息。&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Question&lt;/code&gt;：這裡是我希望 LLM 回應的問題，&lt;code&gt;Which element might customers be interested in?&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;Format&lt;/code&gt;：這裡放了回應格式的規範：用 Element Id 回答我，除此以外不要回答任何字，如果找不到適合的，就說 "&lt;strong&gt;no&lt;/strong&gt;"。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"&lt;strong&gt;no&lt;/strong&gt;" 的部分在&lt;a href="https://dev.to/shunnnet/gei-qian-duan-de-jian-dan-ai-jiao-xue-21-yong-llm-jue-ding-xuan-ran-yuan-su-4inm"&gt;前一篇文章(「以上皆非」 的段落)&lt;/a&gt;有提過，當沒有適合的答案可以回答時，最好給 LLM 一個「選擇」，不然他有可能會強行給一個答案。&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Answer&lt;/code&gt;：給 LLM 填入答案的區塊。這個區塊的概念跟考試會出現的填充題的格子一樣，暗示 LLM 填入答案。&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2.3 DOM 元素的 prompt
&lt;/h3&gt;

&lt;p&gt;終於要把 DOM 元素放進去了。&lt;/p&gt;

&lt;p&gt;還記得前面已經把元素的資訊、ID 都標好了，我們可以使用 Web API 把他們取回來。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;eles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`[data-ai-id]`&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;先說一下，我要做成這樣的 prompt：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;""Element: login-button""
Id: login-button
Description: The button, when clicked, can open a login popup.

""Element: unsubscribe-button""
Id: unsubscribe-button
Description: Clicking it will terminate users subscription of browser-ai.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;跟前面的「段落」很像，只是這次我使用的是&lt;strong&gt;兩個&lt;/strong&gt; &lt;code&gt;"&lt;/code&gt;。因為等等要把他們插入大的段落中，為了跟大段落區隔，所以使用&lt;strong&gt;兩個&lt;/strong&gt;，意圖表明這是&lt;strong&gt;小段落&lt;/strong&gt;。&lt;/p&gt;

&lt;p&gt;然後我在每一段加上元素的相關資訊，好讓 LLM 了解「這個元素的用途是什麼，有什麼內容」，以及他們的 ID。&lt;/p&gt;

&lt;p&gt;知道目標的格式之後，就可以把他們算出來了：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;eles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`[data-ai-id]`&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;elementPrompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;eles&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ele&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`""Element: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;ele&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aiId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;""
Id: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;ele&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aiId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;
Description: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;ele&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aiDescription&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;然後我們把做好的 &lt;code&gt;elementPrompt&lt;/code&gt;，加入大的 &lt;code&gt;prompt&lt;/code&gt; 中。&lt;/p&gt;

&lt;p&gt;我放在 Format 的區塊中：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
  &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Reading the content in "Content" section, and answer the question in "Question" section with strictly follow the instruction in "Format" section.

"""Content"""
user: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;userMessage&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;

"""Question"""
Which element might customers be interested in?

"""Format"""
You must answer with one of the following Element Id with no other words. If you cannot determine, just say '__no__'.

&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;elementPrompt&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;

"""Answer"""

`&lt;/span&gt;
&lt;span class="p"&gt;}]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. 連接起來
&lt;/h2&gt;

&lt;p&gt;最後一步，在表單提交時，我們要把輸入的訊息傳給 GPT，然後根據 GPT 的回應，取得 DOM 元素。&lt;/p&gt;

&lt;p&gt;建議大家直接沿用上一篇的程式碼，或是使用這一篇的原始碼：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleSubmit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userMessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;
  &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reset&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="c1"&gt;// ----Produce Element Prompt----&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;eles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`[data-ai-id]`&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;elementPrompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;eles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ele&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`""Element: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;ele&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aiId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;""
Id: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;ele&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aiId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;
Description: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;ele&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aiDescription&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
  &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;// ----Full prompt----&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`Reading the content in "Content" section, and answer the question in "Question" section with strictly follow the instruction in "Format" section.

"""Content"""
user: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;userMessage&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;

"""Question"""
Which element might customers be interested in?

"""Format"""
You must answer with one of the following Element Id with no other words. If you cannot determine, just say '__no__'.

&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;elementPrompt&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;

"""Answer"""

`&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;prompt&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;// 注意，請將 temperature 設定為 0&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;aiResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;chatCompletion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;aiResponse&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// 以下省略......&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;注意，請將 &lt;code&gt;temperature&lt;/code&gt; 設定為 &lt;code&gt;0&lt;/code&gt;，以提高成功率。&lt;/p&gt;

&lt;p&gt;然後，試著在表單說些跟元素有關的訊息：「我想要登入」，接著看看 &lt;code&gt;console&lt;/code&gt; 是不是回應：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;login-button
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;有這個 ID 之後，就可以取得 DOM 元素了。&lt;/p&gt;

&lt;p&gt;取得 DOM 元素後，可以拿來做什麼？&lt;/p&gt;

&lt;p&gt;一個比較簡單可以想到的例子：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;aiResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;chatCompletion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// 取得對應的元素&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`[data-ai-id="&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;aiResponse&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"]`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// 如果有對應元素，則加上 class ".highlight"&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;highlight&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;或者是&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;scrollIntoView&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;諸如此類的等等...這交給各位的想像力了。&lt;/p&gt;

&lt;h3&gt;
  
  
  Tip
&lt;/h3&gt;

&lt;p&gt;如果你發現不管怎麼樣都選到 &lt;code&gt;__no__&lt;/code&gt;，或許可以試試看對 &lt;code&gt;data-ai-description&lt;/code&gt; 加上更詳細的描述。&lt;/p&gt;




&lt;h2&gt;
  
  
  收尾
&lt;/h2&gt;

&lt;p&gt;整理一下。這篇文章我們看到了：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;可以將指示加在 &lt;code&gt;userMessage&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;如何指示 GPT 回應問題的方式，並且透過「段落」的這個模式說明問題&lt;/li&gt;
&lt;li&gt;如何將 DOM 的內容加入 prompt 中&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;雖然我是以 DOM 作為範例，但我想，這類的做法在其他的場景也會頗有用途，比如選擇「文件」、「敘述」、「角色」.....甚至是 &lt;code&gt;route&lt;/code&gt;, &lt;code&gt;function&lt;/code&gt;。可以多多嘗試。&lt;/p&gt;

&lt;p&gt;下一篇文章依然會再舉一個 GPT 的範例。&lt;/p&gt;

&lt;h2&gt;
  
  
  Reference
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/shunnNet/browser-ai-tutorial/blob/main/03-choose-dom/index.html"&gt;完整原始碼&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  廣告 - Browser AI Project (In development)
&lt;/h2&gt;

&lt;p&gt;我做的套件 der~&lt;br&gt;
Use &lt;code&gt;Browser AI&lt;/code&gt; to help you build an LLM powered website!&lt;br&gt;
Repository: &lt;a href="https://github.com/shunnNet/browser-ai"&gt;https://github.com/shunnNet/browser-ai&lt;/a&gt;&lt;br&gt;
Website: &lt;a href="https://courageous-manatee-a625e9.netlify.app/"&gt;https://courageous-manatee-a625e9.netlify.app/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>openai</category>
      <category>web</category>
      <category>ai</category>
    </item>
    <item>
      <title>給前端的簡單 AI 教學 - 2.1 用 LLM 決定渲染元素</title>
      <dc:creator>shunnNet</dc:creator>
      <pubDate>Fri, 15 Dec 2023 16:25:24 +0000</pubDate>
      <link>https://forem.com/shunnnet/gei-qian-duan-de-jian-dan-ai-jiao-xue-21-yong-llm-jue-ding-xuan-ran-yuan-su-4inm</link>
      <guid>https://forem.com/shunnnet/gei-qian-duan-de-jian-dan-ai-jiao-xue-21-yong-llm-jue-ding-xuan-ran-yuan-su-4inm</guid>
      <description>&lt;h2&gt;
  
  
  系列文
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/shunnnet/gei-qian-duan-de-jian-dan-ai-jiao-xue-lian-jie-openai-1e93"&gt;給前端的簡單 AI 教學 - 1. 連接 OpenAI&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  前言
&lt;/h2&gt;

&lt;p&gt;上一篇文章講了怎麼取得 OpenAI API KEY，並且在網頁中打 API 連接 GPT。這一篇會講一個實際在網頁應用 GPT 的簡單範例，並且順便說明一些關於 GPT 的知識。&lt;/p&gt;

&lt;p&gt;網路上有很多在講 LLM 的文章，大多是在說怎麼用 prompt 來生成文章，或是根據文件回答，或是自動做事情之類的。感覺跟瀏覽器端好像都沒有什麼關係。&lt;/p&gt;

&lt;p&gt;不過其實在瀏覽器端還是有可用之處的，而且不需要很複雜的 prompt 就可以做到。&lt;/p&gt;

&lt;p&gt;這篇文章會實作一個「&lt;strong&gt;根據使用者意圖，決定要渲染什麼元素&lt;/strong&gt;」的小功能。你也可以在 github 中找到這篇文章的&lt;a href="https://github.com/shunnNet/browser-ai-tutorial/blob/main/02-choices/index.html"&gt;完整原始碼&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lAAQ52WL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s2icaelxnekqeyoyd5b6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lAAQ52WL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s2icaelxnekqeyoyd5b6.png" alt="流程圖" width="800" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1. 前置作業
&lt;/h2&gt;

&lt;p&gt;首先我們準備一個表單，接收訊息輸入，並且連結 OpenAI GPT。&lt;/p&gt;

&lt;p&gt;打開網頁後，隨便輸入個訊息，就會看到 GPT 的回應在 &lt;code&gt;console&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"chat"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;textarea&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"input"&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/textarea&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Ask&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;my_openai_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;OPENAI_KEY&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;input&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;chat&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;// 接收表單提交&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleSubmit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userMessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;

      &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reset&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userMessage&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;aiResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;chatCompletion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;aiResponse&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// 這個是綁表單事件&lt;/span&gt;
    &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;submit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handleSubmit&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// 連接 OpenAI GPT&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;chatCompletion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://api.openai.com/v1/chat/completions&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Authorization&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Bearer &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;my_openai_key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
          &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gpt-3.5-turbo&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;messages&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. 判斷使用者的意圖
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;temperature&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;前面是很基本的東西，沒有什麼特別的。&lt;/p&gt;

&lt;p&gt;接下來我們要在 GPT 的參數中加個東西 &lt;code&gt;temperature&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;chatCompletion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="nx"&gt;temperature&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="c1"&gt;// Add this line&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gpt-3.5-turbo&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;temperature&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;temperature&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Add this line&lt;/span&gt;
      &lt;span class="na"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;messages&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;temperature&lt;/code&gt; 是 GPT 的一個參數，可以是 &lt;code&gt;0~1&lt;/code&gt; 之間的任一個浮點數(0, 0.1, 0.2, ..., 1)。&lt;/p&gt;

&lt;p&gt;簡單來說，GPT 在生成內容時會生成好幾個內容，並且會為每一個內容標註是正確答案的可能性。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;內容 A, 可能性 0.81
內容 B, 可能性 0.53
內容 C, 可能性 0.51
....
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;然後他會從中選擇一個作為他的答案。&lt;/p&gt;

&lt;p&gt;這時候，如果 &lt;code&gt;temperature&lt;/code&gt; 的值越靠近 &lt;code&gt;0&lt;/code&gt;，他就會比較容易做出保守的選擇，只選可能性比較高的。(避免犯錯)&lt;/p&gt;

&lt;p&gt;而越靠近 &lt;code&gt;1&lt;/code&gt; 的話，他的選擇範圍就會比較廣，比較有可能選擇其他的可能性低的內容。(玩性較高)&lt;/p&gt;

&lt;p&gt;因為這邊我需要他穩定一點 orz，所以我設定成 &lt;code&gt;0&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;systemMessage&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;接著要來加 &lt;code&gt;prompt&lt;/code&gt; 了。我們要加的是 &lt;code&gt;systemMessage&lt;/code&gt;。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleSubmit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;//...&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="c1"&gt;// This is systemMessage&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;system&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;According to the following conversation, what is user's purpose?&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;

    &lt;span class="c1"&gt;// conversation...&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userMessage&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;這裏我們透過 &lt;code&gt;systemMessage&lt;/code&gt; 指示 GPT 「根據對話內容，分析使用者的意圖」。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;systemMessage&lt;/code&gt; 也是 prompt 的一部分，他是提示 GPT 應該如何回話的「指示」。比方說，我曾經下過：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;system&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;你是一隻皮卡丘，講話只會講「皮卡皮卡」&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;之類的。然後他就只會「皮卡皮卡」。&lt;/p&gt;

&lt;p&gt;可能會有人疑惑：「我們跟網頁版 ChatGPT 說話的時候也會說出這種指示，這跟 &lt;code&gt;systemMessage&lt;/code&gt; 有什麼不一樣？」。這個差異有點微妙，會在之後的文章說明。&lt;/p&gt;

&lt;h3&gt;
  
  
  查看 GPT 的回應
&lt;/h3&gt;

&lt;p&gt;接著我們可以寫個內容傳給 GPT 了，在表單中填入你的訊息，按送出之後，你應該會在 &lt;code&gt;console&lt;/code&gt; 看到回覆。&lt;/p&gt;

&lt;p&gt;比方說： &lt;code&gt;請問你們有沒有賣 Mac 28 Pro ?&lt;/code&gt;。GPT 是這樣回答我的：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- AI response --&amp;gt;&lt;/span&gt;
The user's purpose is to inquire about the availability of the Mac 28 Pro at the store.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;回答正確，可是好像不能拿來做什麼。&lt;/p&gt;

&lt;h3&gt;
  
  
  限制 GPT 的回應
&lt;/h3&gt;

&lt;p&gt;前面提到，我們可以限制 GPT 的回應方式。比方說「你只能講皮卡皮卡」。&lt;/p&gt;

&lt;p&gt;同樣道理，我們限制他只能說出幾個答案：&lt;code&gt;shopping&lt;/code&gt; 或 &lt;code&gt;login&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt; 
  &lt;span class="nl"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;system&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;According to the following conversation, what is user's purpose? You must answer with one of 'shopping', 'login' &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; 
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;透過 &lt;code&gt;You must answer with one of 'shopping', 'login'&lt;/code&gt; 限制他只能回答這兩個。&lt;/p&gt;

&lt;p&gt;加上了之後，我們再試試同樣的訊息： &lt;code&gt;請問你們有沒有賣 Mac 28 Pro ?&lt;/code&gt;，這次他的回應是：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- AI response --&amp;gt;&lt;/span&gt;
shopping
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;如果是固定選項中的常數值，那就很有用途了，比方說：根據不同的意圖，決定要顯示什麼內容。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleSubmit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;system&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;According to the following conversation, what is user's purpose? You must answer with one of 'shopping', 'login' &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userMessage&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="c1"&gt;// Detemine user's purpose&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;aiResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;chatCompletion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;// Do something according to user's purpose&lt;/span&gt;
  &lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;aiResponse&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;shopping&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;// purpose: shopping&lt;/span&gt;
      &lt;span class="nf"&gt;renderProducts&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// show products&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;login&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;// purpose: login&lt;/span&gt;
      &lt;span class="nf"&gt;renderLoginForm&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// show LoginForm&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;這是一個非常基礎的分類問題的 prompt。OpenAI GPT 雖然不是專門用來分類的模型，但是也具備處理這種問題的能力。&lt;/p&gt;

&lt;p&gt;如果你喜歡，也可以加入更多的選項，比方說：'logout', 'asking question', 'contact customer service' ......。總之，透過這個 prompt，我們可以隨著聊天內容，提供使用者他需要的東西。&lt;/p&gt;

&lt;h3&gt;
  
  
  以上皆非
&lt;/h3&gt;

&lt;p&gt;以上已經將基本概念講得差不多了，這裡進行一個重要的補充。&lt;/p&gt;

&lt;p&gt;通常這種「選擇題」的 &lt;code&gt;prompt&lt;/code&gt;，會加上一個「以上皆非」的選項給他。&lt;/p&gt;

&lt;p&gt;因為我們在 &lt;code&gt;systemMessage&lt;/code&gt; 中限制他只能回答 &lt;code&gt;shopping&lt;/code&gt; 或 &lt;code&gt;login&lt;/code&gt;。萬一使用者的意圖是以上皆非，GPT 有沒有可能會仍然回答&lt;code&gt;shopping&lt;/code&gt; ？&lt;/p&gt;

&lt;p&gt;答案是：有可能。&lt;/p&gt;

&lt;p&gt;為了避免這種判斷錯誤的情況，通常會在最後加上一段「以上皆非」、「無法回答」時要怎麼回答的提示，比如&lt;code&gt;「若你不知道怎麼回答，請說 I don't know」&lt;/code&gt;。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt; 
  &lt;span class="nl"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;system&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;According to the following conversation, what is user's purpose? You must answer with one of 'shopping', 'login' with no other words. If you cannot determine, say '__no__'.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;「以上皆非」的內容根據你的需求而定。比如也可以說&lt;code&gt;「如果無法從以下對話判斷，請說 "誰知道"」&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;處理 LLM 模型回應的重點是：他有可能給出錯誤的回應，所以要記得處理這種錯誤。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;aiResponse&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;shopping&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;// purpose: shopping&lt;/span&gt;
    &lt;span class="nf"&gt;renderProducts&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// show products&lt;/span&gt;
    &lt;span class="k"&gt;break&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;login&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;// purpose: login&lt;/span&gt;
    &lt;span class="nf"&gt;renderLoginForm&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// show LoginForm&lt;/span&gt;
    &lt;span class="k"&gt;break&lt;/span&gt;

  &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;// handle __no__&lt;/span&gt;
    &lt;span class="nf"&gt;doSomething&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. 回應使用者
&lt;/h2&gt;

&lt;p&gt;收個尾吧。&lt;/p&gt;

&lt;p&gt;判斷完使用者意圖了，也根據意圖顯示使用者介面了，接著我們讓 GPT 回應他吧。&lt;/p&gt;

&lt;p&gt;在 switch 之後，再度呼叫 GPT。這次我們使用不太一樣的 prompt 與設定。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleSubmit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;system&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;According to the following conversation, what is user's purpose? You must answer with one of 'shopping', 'login' with no other words. If you cannot determine, just say '__no__'.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userMessage&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;aiResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;chatCompletion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;aiResponse&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;shopping&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;// purpose: shopping&lt;/span&gt;
      &lt;span class="nf"&gt;renderProducts&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// show products&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;login&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;// purpose: login&lt;/span&gt;
      &lt;span class="nf"&gt;renderLoginForm&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// show LoginForm&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;

    &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;// handle __no__&lt;/span&gt;
      &lt;span class="nf"&gt;doSomething&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// ! We ask GPT answer user's question here.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;messages2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;system&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;You are friendly customer service. Tell user we already show product him/her wants and other recommend products.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userMessage&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;

  &lt;span class="c1"&gt;// The chatComplete second parameter is `temperature`&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;aiResponse2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;chatCompletion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;messages2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;aiResponse2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;由於是用來回話的，所以 prompt 也不同。&lt;/p&gt;

&lt;p&gt;首先是加上了 customer service 的角色設定。然後那句 &lt;code&gt;Tell user we already show products for him/her.&lt;/code&gt; 則可以根據先前進行過什麼操作決定。&lt;/p&gt;

&lt;p&gt;接著，注意一下，&lt;code&gt;temperature&lt;/code&gt; 的設定不太相同：稍微調高了&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// The chatComplete second parameter is `temperature`&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;aiResponse2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;chatCompletion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;messages2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;其實設定成 &lt;code&gt;0&lt;/code&gt; 也可以。但如果你希望他可以回應的多變一點，不需要那麼考慮正確性的話，這種場景，是可以考慮調高 &lt;code&gt;temperature&lt;/code&gt; 的。&lt;/p&gt;

&lt;p&gt;以下是對話與回應：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;user: 請問你們有沒有賣 Mac 28 Pro ?
assistant: 親愛的顧客，非常感謝您的詢問！很高興告訴您，我們已經展示了 Mac 28 Pro 這款產品。如果您有任何其他問題或需要進一步了解該產品的詳細資訊，請隨時告訴我們。我們很樂意為您提供協助！
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;他也有可能說「我們沒有這個商品，但是已經為您展示了商品清單」之類的 orz。&lt;/p&gt;

&lt;p&gt;礙於篇幅，這邊就留到之後再說怎麼改善這種情況了。&lt;/p&gt;




&lt;h2&gt;
  
  
  收尾
&lt;/h2&gt;

&lt;p&gt;整理一下。這篇文章我們看到了：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;temperature&lt;/code&gt; 的作用：可以決定 GPT 的選擇策略要保守(&lt;code&gt;0&lt;/code&gt;) 還是 冒險一點 (&lt;code&gt;1&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;systemMessage：是&lt;/code&gt; &lt;code&gt;prompt&lt;/code&gt; 的一部分，可以用來指示 GPT 要怎麼回應。&lt;/li&gt;
&lt;li&gt;簡單的分類、選擇的 &lt;code&gt;prompt：我們用來判斷使用者的意圖，並做出對應的行為。&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;下次會講另一個在瀏覽器中應用 OpenAI GPT 的範例。&lt;/p&gt;

&lt;h2&gt;
  
  
  Reference
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/shunnNet/browser-ai-tutorial/blob/main/02-choices/index.html"&gt;完整原始碼&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Advertisment - Browser AI
&lt;/h2&gt;

&lt;p&gt;我做的套件 der~&lt;/p&gt;

&lt;p&gt;Use &lt;code&gt;Browser AI&lt;/code&gt; to help you build an LLM powered website!&lt;br&gt;
&lt;a href="https://courageous-manatee-a625e9.netlify.app/"&gt;https://courageous-manatee-a625e9.netlify.app/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>openai</category>
      <category>web</category>
      <category>frontend</category>
    </item>
    <item>
      <title>給前端的簡單 AI 教學 - 1. 連接 OpenAI</title>
      <dc:creator>shunnNet</dc:creator>
      <pubDate>Mon, 11 Dec 2023 14:41:11 +0000</pubDate>
      <link>https://forem.com/shunnnet/gei-qian-duan-de-jian-dan-ai-jiao-xue-lian-jie-openai-1e93</link>
      <guid>https://forem.com/shunnnet/gei-qian-duan-de-jian-dan-ai-jiao-xue-lian-jie-openai-1e93</guid>
      <description>&lt;h2&gt;
  
  
  前言
&lt;/h2&gt;

&lt;p&gt;這應該會是一連串文章的第一篇，分享一下小弟這一年來開發 LLM 相關應用程式的一些知識跟心得。整個系列會帶過以下內容：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;如何使用 &lt;code&gt;OpenAI&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;簡單的 &lt;code&gt;prompt&lt;/code&gt; 知識&lt;/li&gt;
&lt;li&gt;&lt;code&gt;function_call&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;簡單帶一下 &lt;code&gt;Langchain&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;如何讓 LLM 根據公司的文件回應&lt;/li&gt;
&lt;li&gt;可以怎麼使用 &lt;a href="https://courageous-manatee-a625e9.netlify.app/" rel="noopener noreferrer"&gt;&lt;code&gt;Browser AI&lt;/code&gt;&lt;/a&gt; 套件與前端框架進行整合&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  主題
&lt;/h2&gt;

&lt;p&gt;這篇文章要講很～簡單的東西，就是把 OpenAI 的 API 接起來，大約十分鐘就可以做完。以下是兩個大步驟：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;取得 API KEY&lt;/li&gt;
&lt;li&gt;在網頁打 Request&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  A. 取得 OpenAI API KEY
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. 到 &lt;strong&gt;OpenAI&lt;/strong&gt; 註冊一個帳號
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://platform.openai.com/docs/introduction" rel="noopener noreferrer"&gt;https://platform.openai.com/docs/introduction&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;你應該畫面會在右上角看到 &lt;strong&gt;sign up&lt;/strong&gt;，點下去就會進入註冊流程。跟著註冊流程建立帳號就行了。&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frj244vizgzoewz2kbcox.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frj244vizgzoewz2kbcox.png" alt="OpenAI - sign up"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  2. 確認額度
&lt;/h4&gt;

&lt;p&gt;註冊完後，會回到文件的畫面，你可以點擊左方的 settings &amp;gt; Limits，然後滾動到最下方，會看到下面有一段文字。這段文字是說，你現在是免費方案，要用到 5 美金之後才會開始付費。只是摸一摸的話這金額很足夠的。&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc9y54igfsttinxgtp8r7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc9y54igfsttinxgtp8r7.png" alt="OpenAI - free tier"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;你也可以到左邊點擊 Usage 確認你的使用量：&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv2vbug0jogtjjif6w0jh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv2vbug0jogtjjif6w0jh.png" alt="OpenAI - free tier usage"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  3. 取得 API key
&lt;/h4&gt;

&lt;p&gt;到左側點擊 "API keys"，會進入下圖中的頁面&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn944obnjk2fnqiabkb4r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn944obnjk2fnqiabkb4r.png" alt="OpenAI - api key page"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;要建立 API key，要先做手機驗證，點擊下圖中的按鈕，跟著步驟進行即可&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fonuce42z5o500ziijlrw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fonuce42z5o500ziijlrw.png" alt="OpenAI - verify phone number button"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;手機驗證完之後，然後點擊 "&lt;strong&gt;Create new secret key&lt;/strong&gt;"&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0caxkituw57xkxm4drik.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0caxkituw57xkxm4drik.png" alt="OpenAI - create new secret key button"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;這邊稍微要注意一下：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;首先會需要輸入一個名稱，取個簡單的名稱就好&lt;/li&gt;
&lt;li&gt;送出名字後，在同一個彈窗會出現 API KEY。把 Key 複製下來，藏好不要給別人知道。&lt;/li&gt;
&lt;li&gt;如果你不小心把這個彈窗關掉，又沒有複製到 Key 的話，就把現有的 Key 刪掉，重新建一個 Key 就行。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8ynpg9dhsq06gylk0t1o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8ynpg9dhsq06gylk0t1o.png" alt="OpenAI - Enter new secret key name"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fodi3fxoo8sam1jxer49l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fodi3fxoo8sam1jxer49l.png" alt="OpenAI - Copy new secret key value"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;有了 API key 之後，就可以開始打 API 啦～&lt;/p&gt;
&lt;h3&gt;
  
  
  B. 在網頁中呼叫 gpt
&lt;/h3&gt;

&lt;p&gt;準備好 API key 之後，接著要來呼叫最常用的 &lt;code&gt;chatCompletion&lt;/code&gt; API &lt;/p&gt;

&lt;p&gt;建立一個 html 文件，然後使用以下的程式碼：（記得把 你的 API key 放到變數裡面）&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"ask"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Ask&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;my_openai_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Paste your key here&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;chatCompletion&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://api.openai.com/v1/chat/completions&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,{&lt;/span&gt;
        &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Authorization&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Bearer &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;my_openai_key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
          &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gpt-3.5-turbo&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello ChatGPT&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;
          &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ask&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;chatCompletion&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;然後打開這個 html，點擊 Ask 按鈕，等一下下，你應該會看到以下的回應，就表示成功接起來了～&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0hb30ajoir1o5pxjcths.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0hb30ajoir1o5pxjcths.png" alt="Chat completion API result"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;如果你想要進一步對話，就把 AI 的回應複製下來，然後加到 messages 陣列中，然後加上你的訊息，像以下這樣：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
     &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gpt-3.5-turbo&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="na"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
       &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello ChatGPT&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;

       &lt;span class="c1"&gt;// Put ai response here like this&lt;/span&gt;
       &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;assistant&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello, how can I assist you today?&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;

       &lt;span class="c1"&gt;// Then add user response here&lt;/span&gt;
       &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;I just want to say hi&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
     &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;然後再點擊一次 Ask 按鈕，你就會看到他回應新的內容。&lt;/p&gt;




&lt;p&gt;那麼這篇文章先到這邊&lt;/p&gt;

&lt;p&gt;下一篇文章會來說一下，怎麼讓 &lt;code&gt;OpenAI&lt;/code&gt; gpt 做出你要的回應&lt;/p&gt;




&lt;h2&gt;
  
  
  Reference
&lt;/h2&gt;

&lt;p&gt;這是我們剛剛呼叫的 &lt;code&gt;chatCompletion&lt;/code&gt; API 的規格跟說明文件，有興趣的話可以再研究看看&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://platform.openai.com/docs/guides/text-generation" rel="noopener noreferrer"&gt;OpenAI - Text generation&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://platform.openai.com/docs/api-reference/chat/create" rel="noopener noreferrer"&gt;OpenAI - Create chat completion&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Advertisment - Browser AI
&lt;/h2&gt;

&lt;p&gt;Use &lt;code&gt;Browser AI&lt;/code&gt; to help you build an LLM powered website!&lt;br&gt;
&lt;a href="https://courageous-manatee-a625e9.netlify.app/" rel="noopener noreferrer"&gt;https://courageous-manatee-a625e9.netlify.app/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>openai</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Browser AI project - Package for building AI-Powered Web Application</title>
      <dc:creator>shunnNet</dc:creator>
      <pubDate>Fri, 08 Dec 2023 10:51:57 +0000</pubDate>
      <link>https://forem.com/shunnnet/browser-ai-project-1730</link>
      <guid>https://forem.com/shunnnet/browser-ai-project-1730</guid>
      <description>&lt;p&gt;I made a project called &lt;code&gt;Browser AI&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This is a tool library for developing AI web applications at browser side, especially tailored for business applications that require compliance with rules.&lt;/p&gt;

&lt;p&gt;This library can assist you in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Integrating LLM functionality with business logic.&lt;/li&gt;
&lt;li&gt;Translating user natural language into UI actions or executing specific functions.&lt;/li&gt;
&lt;li&gt;Navigating and guiding users.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can refer to the conceptual demonstration repository &lt;a href="https://github.com/shunnNet/ai-vue-concept"&gt;ai-vue-concept&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Simple: No complicate setting or parameters.&lt;/li&gt;
&lt;li&gt;Atomic: Atomic-level natural language functions. (.is(), .whichIs(), etc.)&lt;/li&gt;
&lt;li&gt;Framework integration: (&lt;code&gt;Vue&lt;/code&gt; only currently):
Easily annotate node, routing information and incorporate prompts&lt;/li&gt;
&lt;li&gt;Render component in LLM message&lt;/li&gt;
&lt;li&gt;Typed: Support Typescript.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Doc
&lt;/h2&gt;

&lt;p&gt;You can check more info at:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://courageous-manatee-a625e9.netlify.app/"&gt;documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/shunnNet/browser-ai"&gt;github&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Although it is still un-stable (I think I should make something like testing and more consideration), the basic functionalities are complete. So you can try to play with that.&lt;/p&gt;

</description>
      <category>vue</category>
      <category>browser</category>
      <category>openai</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
