{"id":3143,"date":"2023-04-06T13:32:11","date_gmt":"2023-04-06T20:32:11","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/surface-duo\/?p=3143"},"modified":"2024-01-03T16:26:46","modified_gmt":"2024-01-04T00:26:46","slug":"android-openai-chatgpt-2","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/surface-duo\/android-openai-chatgpt-2\/","title":{"rendered":"ChatGPT on Android with OpenAI"},"content":{"rendered":"<p>\n  Hello prompt engineers,\n<\/p>\n<p>\n  OpenAI has been in the news a lot recently, with the release of ChatGPT 4 and the integration of Large Language Model (LLM)-driven features into a variety of products and services including Bing, GitHub, and Microsoft 365 applications.\n<\/p>\n<p>\n  Inspired by Syncfusion\u2019s blog post on adding <a href=\"https:\/\/www.syncfusion.com\/blogs\/post\/integrate-chatgpt-blazor-rich-text-editor.aspx\">ChatGPT to their .NET blazor text editor<\/a>, in this post I\u2019m going to add a similar feature to our existing Android <em>Source Editor<\/em> sample. You can view Syncfusion\u2019s <a href=\"https:\/\/github.com\/SyncfusionExamples\/Integrating-OpenAI-with-Blazor-RichTextEditor\">C# implementation on GitHub<\/a> and our simplified Kotlin version in this <a href=\"https:\/\/microsoft.sharepoint-df.com\/teams\/MicrosoftDuoDevXTeam\/Shared%20Documents\/Developer%20-%20Outreach%20-%20Weekly%20Blogs\/TK\">pull request<\/a>.\n<\/p>\n<h2>Get started with OpenAI<\/h2>\n<p>\n  To get started with OpenAI, sign up on the <a href=\"https:\/\/platform.openai.com\/overview\">platform developers page<\/a> and take a look at the <a href=\"https:\/\/platform.openai.com\/docs\/introduction\">documentation<\/a>. Although there is a free tier that provides a limited number of requests, I signed up for a paid account (and set a reasonable paid limit). Once you have an account you can immediately try the interactive chat experience at <a href=\"https:\/\/chat.openai.com\/\">chat.openai.com<\/a>. \n<\/p>\n<blockquote><p>If you are completely new to ChatGPT, consider following the <a href=\"https:\/\/platform.openai.com\/docs\/quickstart\/introduction\">quickstart<\/a> and reviewing some <a href=\"https:\/\/platform.openai.com\/examples\">examples<\/a> before continuing.<\/p><\/blockquote>\n<p>\n  We can start to test our prompt ideas directly in the ChatGPT UI with the HTML content <a href=\"https:\/\/github.com\/conceptdev\/surface-duo-window-manager-samples\/blob\/main\/SourceEditor\/app\/src\/main\/assets\/source.html\">embedded<\/a> in the demo.\n<\/p>\n<p>\n  These are two prompts that we\u2019ll add to our Android demo:\n<\/p>\n<pre>SHORTEN = \"Strip away extra words in the below html content and provide a clear message as html content.\\n\\n\"\r\nGRAMMARCHECK = \"Check grammar and spelling in the below html content and provide the result as html content.\\n\\n\"<\/pre>\n<p>\n  Here\u2019s a screenshot showing the test ChatGPT interaction \u2013 the entire query consists of the prompt text followed by the HTML content, and the output contains the result:\n<\/p>\n<p>\n  <img decoding=\"async\" width=\"2500\" height=\"1190\" src=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2023\/04\/graphical-user-interface-text-application-descr.png\" class=\"wp-image-3144\" alt=\"Screenshot of a ChatGPT interaction testing a spell checking prompt with HTML content\" srcset=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2023\/04\/graphical-user-interface-text-application-descr.png 2500w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2023\/04\/graphical-user-interface-text-application-descr-300x143.png 300w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2023\/04\/graphical-user-interface-text-application-descr-1024x487.png 1024w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2023\/04\/graphical-user-interface-text-application-descr-768x366.png 768w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2023\/04\/graphical-user-interface-text-application-descr-1536x731.png 1536w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2023\/04\/graphical-user-interface-text-application-descr-2048x975.png 2048w\" sizes=\"(max-width: 2500px) 100vw, 2500px\" \/>\n<\/p>\n<p><em>Figure 1: Using ChatGPT to summarize an existing HTML page \u2013 prompt on the left and resulting \u2018summarized\u2019 HTML on the right<\/em>\n<\/p>\n<p>\n  Test both prompts \u2013 a short summary and a grammar- and spell-checked version of the content. To better test the spell checking feature, add some intentionally bad typos and grammar into your test data. You can continue to experiment with different prompts to achieve many different text outputs, but once you\u2019re finished playing, keep reading to get started with the developer API.\n<\/p>\n<h2>OpenAI API<\/h2>\n<p>\n  Because we want to access ChatGPT from an Android application, we\u2019ll need to use the provided API. The API consists of web requests and responses in a JSON format, using an authentication header for access control and billing.\n<\/p>\n<p>\n  When you are logged in to OpenAI you can generate authentication tokens from <a href=\"https:\/\/platform.openai.com\/account\/api-keys\">this page<\/a>, and then you can test any of the <a href=\"https:\/\/platform.openai.com\/docs\/api-reference\/completions\/create\">API endpoints listed in the documentation<\/a> using cURL, such as the <code>completions<\/code> endpoint that we will use in our demo:\n<\/p>\n<p>\n  <img decoding=\"async\" width=\"924\" height=\"502\" src=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2023\/04\/text-description-automatically-generated.png\" class=\"wp-image-3145\" alt=\"Screenshot of the OpenAI help page for the completions endpoint CURL example JSON request\" srcset=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2023\/04\/text-description-automatically-generated.png 924w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2023\/04\/text-description-automatically-generated-300x163.png 300w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2023\/04\/text-description-automatically-generated-768x417.png 768w\" sizes=\"(max-width: 924px) 100vw, 924px\" \/>\n<\/p>\n<p><em>Figure 2: Accessing the OpenAI API via curl<\/em>\n<\/p>\n<p>\n  Once you have confirmed that your API key is working using cURL, you can modify the <code>prompt<\/code> text to use the test content from above (don\u2019t forget to make sure it\u2019s valid JSON). Once you\u2019re happy with the results from the API, it\u2019s time to add these features to the Android app.\n<\/p>\n<h2>Adding to Android<\/h2>\n<p>\n  For this example, we\u2019re going to make three fairly minor changes to the existing <a href=\"https:\/\/github.com\/microsoft\/surface-duo-window-manager-samples\/tree\/main\/SourceEditor\"><em>Source Editor<\/em><\/a> Android sample app:\n<\/p>\n<ul>\n<li>\n    A new class for OpenAPI-specific information like authorization key, endpoint URL, and prompt text\n  <\/li>\n<li>\n    A method that creates the OpenAPI JSON request, sends it via an <code>HttpClient<\/code>, and parses the result\n  <\/li>\n<li>\n    UI changes to add ChatGPT feature buttons to the navigation bar\n  <\/li>\n<\/ul>\n<p>\n  You can easily browse the changes in this <a href=\"https:\/\/github.com\/conceptdev\/surface-duo-window-manager-samples\/pull\/1\/files\">pull request on GitHub<\/a>.\n<\/p>\n<h3>Constants class<\/h3>\n<p>\n  This class contains the API details needed to access ChatGPT, including the URL and your API key (remember to keep this secret, and DON\u2019T check it into source control):\n<\/p>\n<pre>internal object Constants {\r\n   \/\/ The OpenAI API key.\r\n   internal const val OPENAI_KEY = \"{OPENAPI_API_KEY_GOES_HERE}\"\r\n   \/\/ The OpenAI API model name.\r\n   internal const val OPENAI_MODEL_COMPLETIONS = \"text-davinci-003\"\r\n   \/\/ The OpenAI API endpoint.\r\n   internal const val API_ENDPOINT_COMPLETIONS = \"https:\/\/api.openai.com\/v1\/completions\"\r\n   \/\/ ChatGPT prompts.\r\n   internal const val SHORTEN = \"Strip away extra words in the below html content and provide a clear message as html content.\\n\\n\"\r\n   internal const val GRAMMARCHECK = \"Check grammar and spelling in the below html content and provide the result as html content.\\n\\n\"\r\n}<\/pre>\n<h3>HttpClient API method<\/h3>\n<p>\n  This method is called from the new feature buttons, and it passes in the prompt to be sent to ChatGPT. The code formats a valid JSON body, constructs the HTTP request with the required authorization header, and parses the ChatGPT answer from valid responses:\n<\/p>\n<pre>private suspend fun createCompletion(prompt: String): String {\r\n   val openAIPrompt = mapOf(\r\n      \"model\" to Constants.OPENAI_MODEL_COMPLETIONS,\r\n      \"prompt\" to prompt,\r\n      \"temperature\" to 0.5,\r\n      \"max_tokens\" to 1500,\r\n   )\r\n   val content:String = gson.toJson(openAIPrompt).toString()\r\n   val response = httpClient.post(Constants.API_ENDPOINT_COMPLETIONS) {\r\n       headers {\r\n         append(HttpHeaders.Authorization, \"Bearer \" + Constants.OPENAI_KEY)\r\n      }\r\n      contentType(ContentType.Application.Json)\r\n      setBody (content)\r\n   }\r\n   if (response.status == HttpStatusCode.OK) {\r\n      val jsonContent = response.bodyAsText()\r\n      val choices = Json.parseToJsonElement(jsonContent).jsonObject[\"choices\"]!!.toString()\r\n      val result = Json.parseToJsonElement(choices.removeSurrounding(\"[\", \"]\"))\r\n      var text = result.jsonObject[\"text\"]!!.toString()\r\n      return text\r\n   }\r\n   \/\/ Other Http status codes\r\n   return \"Not OK status: \" + response.status\r\n}<\/pre>\n<p>\n  The code shown above is edited for clarity \u2013 the <a href=\"https:\/\/github.com\/conceptdev\/surface-duo-window-manager-samples\/blob\/ba7780d2eb4e0b93485870c7b76b8faf520380ad\/SourceEditor\/app\/src\/main\/java\/com\/microsoft\/device\/display\/wm_samples\/sourceeditor\/MainActivity.kt#L232\">sample on GitHub<\/a> has more configuration options and error handling.\n<\/p>\n<h3>UI updates<\/h3>\n<p>\n  In order to call the ChatGPT features, new SVG images resources are added to the project, included in <strong>component_action_toolbar.xml<\/strong>, and wired up with calls to the <code>createCompletion<\/code> method in <strong>MainActivity.kt<\/strong>. \n<\/p>\n<h3>Testing the demo<\/h3>\n<p>\n  The ChatGPT API call is triggered by new buttons added to the navigation bar. Run the sample (which now includes purposeful typos in the HTML, highlighted on the left screenshot in Figure 3) and choose either of the new grammar or summarization features via the toolbar buttons. After a short delay for the network request and processing time, the editable content and preview will be updated with the results from the OpenAI service:\n<\/p>\n<p>\n  <img decoding=\"async\" width=\"1600\" height=\"643\" src=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2023\/04\/word-image-3143-3.png\" class=\"wp-image-3146\" srcset=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2023\/04\/word-image-3143-3.png 1600w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2023\/04\/word-image-3143-3-300x121.png 300w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2023\/04\/word-image-3143-3-1024x412.png 1024w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2023\/04\/word-image-3143-3-768x309.png 768w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2023\/04\/word-image-3143-3-1536x617.png 1536w\" sizes=\"(max-width: 1600px) 100vw, 1600px\" \/>\n<\/p>\n<p><em>Figure 3: Android application showing the original (typos highlighted manually) and results of the <code>GRAMMARCHECK<\/code> and <code>SHORTEN<\/code> prompts on the source HTML.<\/em>\n<\/p>\n<p>\n  An interesting side-effect of the <code>SHORTEN<\/code> prompt is that even though it doesn\u2019t contain an explicit request to fix spelling and grammar, the output does not contain the typos present in the source HTML. In both cases, the HTML formatting and links are preserved. Both prompts also preserve the <strong>DisplayFeature<\/strong> and <strong>FoldingFeature<\/strong> enum names, even though they are not \u2018correctly spelled\u2019 according to any dictionary.\n<\/p>\n<p>\n  These prompts are just two examples of features that might make sense in a text editor application. Other things you could try include making the content more or less formal, translating to other languages, changing the formatting (eg. from HTML to Markdown), or providing an input for the user to generate content from their own prompts. An undo feature would also be useful if you\u2019re unhappy with the final results!\n<\/p>\n<h2>Feedback and resources<\/h2>\n<p>\n  Here\u2019s a summary of the links shared in this post:\n<\/p>\n<ul>\n<li><a href=\"https:\/\/platform.openai.com\/docs\/introduction\">OpenAI documentation<\/a>\n  <\/li>\n<li><a href=\"https:\/\/platform.openai.com\/docs\/api-reference\/introduction\">OpenAI API reference<\/a>\n  <\/li>\n<li><a href=\"https:\/\/www.syncfusion.com\/blogs\/post\/integrate-chatgpt-blazor-rich-text-editor.aspx\">Syncfusion blog<\/a>\n  <\/li>\n<li><a href=\"https:\/\/github.com\/conceptdev\/surface-duo-window-manager-samples\/pull\/1\">Updated Source Editor code on GitHub<\/a>\n  <\/li>\n<\/ul>\n<p>\n  If you have any questions about ChatGPT or how to apply AI in your apps, use the <a href=\"http:\/\/aka.ms\/SurfaceDuoSDK-Feedback\">feedback forum<\/a> or message us on <a href=\"https:\/\/twitter.com\/surfaceduodev\">Twitter @surfaceduodev<\/a>.\n<\/p>\n<p>\n  No livestream this week, but check out the <a href=\"https:\/\/youtube.com\/c\/surfaceduodev\">archives on YouTube<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hello prompt engineers, OpenAI has been in the news a lot recently, with the release of ChatGPT 4 and the integration of Large Language Model (LLM)-driven features into a variety of products and services including Bing, GitHub, and Microsoft 365 applications. Inspired by Syncfusion\u2019s blog post on adding ChatGPT to their .NET blazor text editor, [&hellip;]<\/p>\n","protected":false},"author":570,"featured_media":3144,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[741],"tags":[734,729,733],"class_list":["post-3143","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-ai","tag-chatgpt","tag-machine-learning","tag-openai"],"acf":[],"blog_post_summary":"<p>Hello prompt engineers, OpenAI has been in the news a lot recently, with the release of ChatGPT 4 and the integration of Large Language Model (LLM)-driven features into a variety of products and services including Bing, GitHub, and Microsoft 365 applications. Inspired by Syncfusion\u2019s blog post on adding ChatGPT to their .NET blazor text editor, [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/posts\/3143","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/users\/570"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/comments?post=3143"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/posts\/3143\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/media\/3144"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/media?parent=3143"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/categories?post=3143"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/tags?post=3143"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}