[{"data":1,"prerenderedAt":2766},["ShallowReactive",2],{"blog-\u002Fblog\u002Fen\u002Frevolutionize-your-app-with-chatgpt":3},{"id":4,"title":5,"body":6,"date":2753,"description":2754,"extension":2755,"meta":2756,"navigation":200,"path":2757,"seo":2758,"stem":2759,"tags":2760,"translationSlug":2764,"__hash__":2765},"content\u002Fblog\u002Fen\u002Frevolutionize-your-app-with-chatgpt.md","Revolutionize Your App with ChatGPT - AI Interactions Guide",{"type":7,"value":8,"toc":2742},"minimark",[9,14,18,21,33,36,49,52,60,63,75,81,85,88,95,128,135,143,146,558,565,605,608,640,643,647,656,659,887,890,1014,1017,1046,1056,1174,1177,1181,1184,1562,1569,1572,1675,1678,1682,1685,1712,1715,1718,1723,1726,1943,1946,2115,2118,2185,2188,2191,2255,2259,2262,2358,2361,2404,2412,2415,2457,2460,2464,2467,2588,2709,2718,2729,2732,2735,2738],[10,11,13],"h2",{"id":12},"interacting-with-an-llm","Interacting with an LLM",[15,16,17],"p",{},"Two years ago, ChatGPT democratized the use of AI for the general public. In 2024, it has become common for application users to expect to find an integrated AI in their favorite software, including yours. These new AIs that directly answer all your questions are LLMs (Large Language Models), they predict a coherent response to a question.",[15,19,20],{},"Many sites have started integrating this type of solution, however, few sites fully exploit the potential of the tools they use. Many simply feed a language model with their documentation to answer users and directly integrate ChatGPT or another LLM without a restrictive system prompt, meaning your car dealership's chat, designed to advise you on vehicles, can also help you solve fluid mechanics problems.",[22,23,24,25,24,30],"figure",{},"\n  ",[26,27],"img",{"src":28,"alt":29},"\u002Fblog\u002Fcar-physics.webp","A Chevrolet agency chatbot writing a Python script to solve the Navier-Stokes equations",[31,32,29],"figcaption",{},[15,34,35],{},"LLMs are designed to write text, so if software wants to use the response provided, it must attempt to parse it to retrieve the information it needs. A naive approach might be:",[37,38,39,43,46],"ul",{},[40,41,42],"li",{},"Asking to structure the response in the system prompt, for example: \"In response to the user, provide a short title on one line then skip a line and give the answer.\" The software then attempts to split the response into title \u002F answer",[40,44,45],{},"Making multiple requests with the user's query to get the title then the answer",[40,47,48],{},"Asking the model to produce JSON",[15,50,51],{},"These approaches pose multiple problems. Depending on the user prompt (the part left free to the user) the model can be influenced and modify the response structure, or it may decide on its own not to follow it exactly, adding \"Of course, I can...\" and \"I hope this answer satisfies you\" at the beginning or end.",[15,53,54,55,59],{},"JSON, which appears to be an ideal solution, also poses problems - models tend to generate JSON that doesn't parse. Once you've found the first opening brace and the last closing one, ",[56,57,58],"code",{},"JSON.parse(...)"," throws an error roughly half the time. This rate increases with the size of the requested JSON. Generally, a comma, colon or brace is missing somewhere. Often the generated JSON is not minified and contains lots of line breaks and whitespace, which greatly increases the response size and therefore the number of tokens consumed. An LLM is trained on human-readable textual data, it's not at all familiar with minified JSON.",[15,61,62],{},"The best models for generating JSON are (as of May 2024 and in my experience) those from OpenAI and Mistral.",[15,64,65,66,70,71,74],{},"The APIs provided by companies offering LLMs often go much further than simple Chat completion. OpenAI has offered since June 2023 through its API the ability to provide ",[67,68,69],"strong",{},"tools"," to the model, among these tools, it's possible to define ",[67,72,73],{},"functions"," and the typed arguments of the function. This solves all the problems mentioned above.",[15,76,77,80],{},[67,78,79],{},"The project",": To discover functions, we'll develop a small API for Blue, my reef aquarium management application, allowing interaction with a user. The user can ask a question, and depending on the nature of the question, the model can either respond textually or trigger actions in the application.",[10,82,84],{"id":83},"setting-up-the-environment","Setting up the environment",[15,86,87],{},"If you use OpenAI's APIs, once your account is created, an API key is provided to you. It goes without saying that this key is sensitive - you pay for API usage per token, if your key gets exposed, it can be used by someone else on your budget. It should therefore never appear anywhere, whether in your compiled application code or in your git repo.",[15,89,90,91,94],{},"We'll create a small express server that processes the application's requests. I recommend starting by creating a ",[56,92,93],{},".env"," file at the project root.",[96,97,102],"pre",{"className":98,"code":99,"language":100,"meta":101,"style":101},"language-bash shiki shiki-themes github-dark","# OpenAI API key\nOPENAI_API_KEY=sk-XXXXXXX\n","bash","",[56,103,104,113],{"__ignoreMap":101},[105,106,109],"span",{"class":107,"line":108},"line",1,[105,110,112],{"class":111},"sAwPA","# OpenAI API key\n",[105,114,116,120,124],{"class":107,"line":115},2,[105,117,119],{"class":118},"s95oV","OPENAI_API_KEY",[105,121,123],{"class":122},"snl16","=",[105,125,127],{"class":126},"sU2Wk","sk-XXXXXXX\n",[15,129,130,131,134],{},"This file should not be committed, so add a ",[56,132,133],{},".gitignore"," file at the project root containing:",[96,136,141],{"className":137,"code":139,"language":140,"meta":101},[138],"language-text",".env\n","text",[56,142,139],{"__ignoreMap":101},[15,144,145],{},"Once your key is secured, create your express server.",[96,147,151],{"className":148,"code":149,"language":150,"meta":101,"style":101},"language-javascript shiki shiki-themes github-dark","\u002F\u002F Load configuration from .env if the file exists\nconst dotenv = require(\"dotenv\");\ndotenv.config();\n\n\u002F\u002F Create the express server\nconst express = require(\"express\");\nconst app = express();\n\n\u002F\u002F Load OpenAI api\nconst OpenAI = require(\"openai\");\nconst openai = new OpenAI();\n\n\u002F\u002F Get a random number route\napp.use(\"\u002Frequest\", async function (req, res) {\n  const completion = await openai.chat.completions.create({\n    messages: [\n      {\n        role: \"user\",\n        content: \"Pick a number between 1 and 1000\",\n      },\n    ],\n    model: \"gpt-4o\",\n  });\n  let message = completion.choices[0].message;\n  res.send(message);\n});\n\n\u002F\u002F Start listening\napp.set(\"port\", process.env.PORT || 3000);\napp.listen(app.get(\"port\"), function () {\n  console.log(\"Listening to Port\", app.get(\"port\"));\n});\n","javascript",[56,152,153,158,183,195,202,208,227,241,246,252,271,288,293,299,337,360,366,372,384,395,401,407,418,424,444,456,462,467,473,500,527,553],{"__ignoreMap":101},[105,154,155],{"class":107,"line":108},[105,156,157],{"class":111},"\u002F\u002F Load configuration from .env if the file exists\n",[105,159,160,163,167,170,174,177,180],{"class":107,"line":115},[105,161,162],{"class":122},"const",[105,164,166],{"class":165},"sDLfK"," dotenv",[105,168,169],{"class":122}," =",[105,171,173],{"class":172},"svObZ"," require",[105,175,176],{"class":118},"(",[105,178,179],{"class":126},"\"dotenv\"",[105,181,182],{"class":118},");\n",[105,184,186,189,192],{"class":107,"line":185},3,[105,187,188],{"class":118},"dotenv.",[105,190,191],{"class":172},"config",[105,193,194],{"class":118},"();\n",[105,196,198],{"class":107,"line":197},4,[105,199,201],{"emptyLinePlaceholder":200},true,"\n",[105,203,205],{"class":107,"line":204},5,[105,206,207],{"class":111},"\u002F\u002F Create the express server\n",[105,209,211,213,216,218,220,222,225],{"class":107,"line":210},6,[105,212,162],{"class":122},[105,214,215],{"class":165}," express",[105,217,169],{"class":122},[105,219,173],{"class":172},[105,221,176],{"class":118},[105,223,224],{"class":126},"\"express\"",[105,226,182],{"class":118},[105,228,230,232,235,237,239],{"class":107,"line":229},7,[105,231,162],{"class":122},[105,233,234],{"class":165}," app",[105,236,169],{"class":122},[105,238,215],{"class":172},[105,240,194],{"class":118},[105,242,244],{"class":107,"line":243},8,[105,245,201],{"emptyLinePlaceholder":200},[105,247,249],{"class":107,"line":248},9,[105,250,251],{"class":111},"\u002F\u002F Load OpenAI api\n",[105,253,255,257,260,262,264,266,269],{"class":107,"line":254},10,[105,256,162],{"class":122},[105,258,259],{"class":165}," OpenAI",[105,261,169],{"class":122},[105,263,173],{"class":172},[105,265,176],{"class":118},[105,267,268],{"class":126},"\"openai\"",[105,270,182],{"class":118},[105,272,274,276,279,281,284,286],{"class":107,"line":273},11,[105,275,162],{"class":122},[105,277,278],{"class":165}," openai",[105,280,169],{"class":122},[105,282,283],{"class":122}," new",[105,285,259],{"class":172},[105,287,194],{"class":118},[105,289,291],{"class":107,"line":290},12,[105,292,201],{"emptyLinePlaceholder":200},[105,294,296],{"class":107,"line":295},13,[105,297,298],{"class":111},"\u002F\u002F Get a random number route\n",[105,300,302,305,308,310,313,316,319,322,325,329,331,334],{"class":107,"line":301},14,[105,303,304],{"class":118},"app.",[105,306,307],{"class":172},"use",[105,309,176],{"class":118},[105,311,312],{"class":126},"\"\u002Frequest\"",[105,314,315],{"class":118},", ",[105,317,318],{"class":122},"async",[105,320,321],{"class":122}," function",[105,323,324],{"class":118}," (",[105,326,328],{"class":327},"s9osk","req",[105,330,315],{"class":118},[105,332,333],{"class":327},"res",[105,335,336],{"class":118},") {\n",[105,338,340,343,346,348,351,354,357],{"class":107,"line":339},15,[105,341,342],{"class":122},"  const",[105,344,345],{"class":165}," completion",[105,347,169],{"class":122},[105,349,350],{"class":122}," await",[105,352,353],{"class":118}," openai.chat.completions.",[105,355,356],{"class":172},"create",[105,358,359],{"class":118},"({\n",[105,361,363],{"class":107,"line":362},16,[105,364,365],{"class":118},"    messages: [\n",[105,367,369],{"class":107,"line":368},17,[105,370,371],{"class":118},"      {\n",[105,373,375,378,381],{"class":107,"line":374},18,[105,376,377],{"class":118},"        role: ",[105,379,380],{"class":126},"\"user\"",[105,382,383],{"class":118},",\n",[105,385,387,390,393],{"class":107,"line":386},19,[105,388,389],{"class":118},"        content: ",[105,391,392],{"class":126},"\"Pick a number between 1 and 1000\"",[105,394,383],{"class":118},[105,396,398],{"class":107,"line":397},20,[105,399,400],{"class":118},"      },\n",[105,402,404],{"class":107,"line":403},21,[105,405,406],{"class":118},"    ],\n",[105,408,410,413,416],{"class":107,"line":409},22,[105,411,412],{"class":118},"    model: ",[105,414,415],{"class":126},"\"gpt-4o\"",[105,417,383],{"class":118},[105,419,421],{"class":107,"line":420},23,[105,422,423],{"class":118},"  });\n",[105,425,427,430,433,435,438,441],{"class":107,"line":426},24,[105,428,429],{"class":122},"  let",[105,431,432],{"class":118}," message ",[105,434,123],{"class":122},[105,436,437],{"class":118}," completion.choices[",[105,439,440],{"class":165},"0",[105,442,443],{"class":118},"].message;\n",[105,445,447,450,453],{"class":107,"line":446},25,[105,448,449],{"class":118},"  res.",[105,451,452],{"class":172},"send",[105,454,455],{"class":118},"(message);\n",[105,457,459],{"class":107,"line":458},26,[105,460,461],{"class":118},"});\n",[105,463,465],{"class":107,"line":464},27,[105,466,201],{"emptyLinePlaceholder":200},[105,468,470],{"class":107,"line":469},28,[105,471,472],{"class":111},"\u002F\u002F Start listening\n",[105,474,476,478,481,483,486,489,492,495,498],{"class":107,"line":475},29,[105,477,304],{"class":118},[105,479,480],{"class":172},"set",[105,482,176],{"class":118},[105,484,485],{"class":126},"\"port\"",[105,487,488],{"class":118},", process.env.",[105,490,491],{"class":165},"PORT",[105,493,494],{"class":122}," ||",[105,496,497],{"class":165}," 3000",[105,499,182],{"class":118},[105,501,503,505,508,511,514,516,518,521,524],{"class":107,"line":502},30,[105,504,304],{"class":118},[105,506,507],{"class":172},"listen",[105,509,510],{"class":118},"(app.",[105,512,513],{"class":172},"get",[105,515,176],{"class":118},[105,517,485],{"class":126},[105,519,520],{"class":118},"), ",[105,522,523],{"class":122},"function",[105,525,526],{"class":118}," () {\n",[105,528,530,533,536,538,541,544,546,548,550],{"class":107,"line":529},31,[105,531,532],{"class":118},"  console.",[105,534,535],{"class":172},"log",[105,537,176],{"class":118},[105,539,540],{"class":126},"\"Listening to Port\"",[105,542,543],{"class":118},", app.",[105,545,513],{"class":172},[105,547,176],{"class":118},[105,549,485],{"class":126},[105,551,552],{"class":118},"));\n",[105,554,556],{"class":107,"line":555},32,[105,557,461],{"class":118},[15,559,560,561,564],{},"We start the server and call the ",[56,562,563],{},"\u002Frequest"," route, here's the response:",[96,566,570],{"className":567,"code":568,"language":569,"meta":101,"style":101},"language-json shiki shiki-themes github-dark","{\n  \"role\": \"assistant\",\n  \"content\": \"Sure, let's go with the number 387.\"\n}\n","json",[56,571,572,577,590,600],{"__ignoreMap":101},[105,573,574],{"class":107,"line":108},[105,575,576],{"class":118},"{\n",[105,578,579,582,585,588],{"class":107,"line":115},[105,580,581],{"class":165},"  \"role\"",[105,583,584],{"class":118},": ",[105,586,587],{"class":126},"\"assistant\"",[105,589,383],{"class":118},[105,591,592,595,597],{"class":107,"line":185},[105,593,594],{"class":165},"  \"content\"",[105,596,584],{"class":118},[105,598,599],{"class":126},"\"Sure, let's go with the number 387.\"\n",[105,601,602],{"class":107,"line":197},[105,603,604],{"class":118},"}\n",[15,606,607],{},"Second try:",[96,609,611],{"className":567,"code":610,"language":569,"meta":101,"style":101},"{\n  \"role\": \"assistant\",\n  \"content\": \"Sure! How about 427?\"\n}\n",[56,612,613,617,627,636],{"__ignoreMap":101},[105,614,615],{"class":107,"line":108},[105,616,576],{"class":118},[105,618,619,621,623,625],{"class":107,"line":115},[105,620,581],{"class":165},[105,622,584],{"class":118},[105,624,587],{"class":126},[105,626,383],{"class":118},[105,628,629,631,633],{"class":107,"line":185},[105,630,594],{"class":165},[105,632,584],{"class":118},[105,634,635],{"class":126},"\"Sure! How about 427?\"\n",[105,637,638],{"class":107,"line":197},[105,639,604],{"class":118},[15,641,642],{},"We could extract the number with a regexp, but we'll use a function instead.",[10,644,646],{"id":645},"using-a-function","Using a function",[15,648,649,650,652,653,655],{},"Functions are available in gpt-4o, gpt-4-turbo and gpt-3.5-turbo models. To declare a function, you need to use the ",[56,651,69],{}," attribute of the completion API. For now, ",[56,654,69],{}," only supports functions.",[15,657,658],{},"We modify the OpenAI API call as follows:",[96,660,662],{"className":148,"code":661,"language":150,"meta":101,"style":101},"const completion = await openai.chat.completions.create({\n  messages: [\n    {\n      role: \"system\",\n      content: \"To give a number to the user, use the sendNumber function\",\n    },\n    {\n      role: \"user\",\n      content: \"Pick a number between 1 and 1000\",\n    },\n  ],\n  model: \"gpt-4o\",\n  tools: [\n    {\n      type: \"function\",\n      function: {\n        name: \"sendNumber\",\n        description: \"send a number to the user\",\n        parameters: {\n          type: \"object\",\n          properties: {\n            randomNumber: {\n              type: \"number\",\n            },\n          },\n        },\n      },\n    },\n  ],\n});\nlet message = completion.choices[0].message;\nres.send(message);\n",[56,663,664,680,685,690,700,710,715,719,727,735,739,744,753,758,762,772,777,787,797,802,812,817,822,832,837,842,847,851,855,859,863,878],{"__ignoreMap":101},[105,665,666,668,670,672,674,676,678],{"class":107,"line":108},[105,667,162],{"class":122},[105,669,345],{"class":165},[105,671,169],{"class":122},[105,673,350],{"class":122},[105,675,353],{"class":118},[105,677,356],{"class":172},[105,679,359],{"class":118},[105,681,682],{"class":107,"line":115},[105,683,684],{"class":118},"  messages: [\n",[105,686,687],{"class":107,"line":185},[105,688,689],{"class":118},"    {\n",[105,691,692,695,698],{"class":107,"line":197},[105,693,694],{"class":118},"      role: ",[105,696,697],{"class":126},"\"system\"",[105,699,383],{"class":118},[105,701,702,705,708],{"class":107,"line":204},[105,703,704],{"class":118},"      content: ",[105,706,707],{"class":126},"\"To give a number to the user, use the sendNumber function\"",[105,709,383],{"class":118},[105,711,712],{"class":107,"line":210},[105,713,714],{"class":118},"    },\n",[105,716,717],{"class":107,"line":229},[105,718,689],{"class":118},[105,720,721,723,725],{"class":107,"line":243},[105,722,694],{"class":118},[105,724,380],{"class":126},[105,726,383],{"class":118},[105,728,729,731,733],{"class":107,"line":248},[105,730,704],{"class":118},[105,732,392],{"class":126},[105,734,383],{"class":118},[105,736,737],{"class":107,"line":254},[105,738,714],{"class":118},[105,740,741],{"class":107,"line":273},[105,742,743],{"class":118},"  ],\n",[105,745,746,749,751],{"class":107,"line":290},[105,747,748],{"class":118},"  model: ",[105,750,415],{"class":126},[105,752,383],{"class":118},[105,754,755],{"class":107,"line":295},[105,756,757],{"class":118},"  tools: [\n",[105,759,760],{"class":107,"line":301},[105,761,689],{"class":118},[105,763,764,767,770],{"class":107,"line":339},[105,765,766],{"class":118},"      type: ",[105,768,769],{"class":126},"\"function\"",[105,771,383],{"class":118},[105,773,774],{"class":107,"line":362},[105,775,776],{"class":118},"      function: {\n",[105,778,779,782,785],{"class":107,"line":368},[105,780,781],{"class":118},"        name: ",[105,783,784],{"class":126},"\"sendNumber\"",[105,786,383],{"class":118},[105,788,789,792,795],{"class":107,"line":374},[105,790,791],{"class":118},"        description: ",[105,793,794],{"class":126},"\"send a number to the user\"",[105,796,383],{"class":118},[105,798,799],{"class":107,"line":386},[105,800,801],{"class":118},"        parameters: {\n",[105,803,804,807,810],{"class":107,"line":397},[105,805,806],{"class":118},"          type: ",[105,808,809],{"class":126},"\"object\"",[105,811,383],{"class":118},[105,813,814],{"class":107,"line":403},[105,815,816],{"class":118},"          properties: {\n",[105,818,819],{"class":107,"line":409},[105,820,821],{"class":118},"            randomNumber: {\n",[105,823,824,827,830],{"class":107,"line":420},[105,825,826],{"class":118},"              type: ",[105,828,829],{"class":126},"\"number\"",[105,831,383],{"class":118},[105,833,834],{"class":107,"line":426},[105,835,836],{"class":118},"            },\n",[105,838,839],{"class":107,"line":446},[105,840,841],{"class":118},"          },\n",[105,843,844],{"class":107,"line":458},[105,845,846],{"class":118},"        },\n",[105,848,849],{"class":107,"line":464},[105,850,400],{"class":118},[105,852,853],{"class":107,"line":469},[105,854,714],{"class":118},[105,856,857],{"class":107,"line":475},[105,858,743],{"class":118},[105,860,861],{"class":107,"line":502},[105,862,461],{"class":118},[105,864,865,868,870,872,874,876],{"class":107,"line":529},[105,866,867],{"class":122},"let",[105,869,432],{"class":118},[105,871,123],{"class":122},[105,873,437],{"class":118},[105,875,440],{"class":165},[105,877,443],{"class":118},[105,879,880,883,885],{"class":107,"line":555},[105,881,882],{"class":118},"res.",[105,884,452],{"class":172},[105,886,455],{"class":118},[15,888,889],{},"Response received:",[96,891,893],{"className":567,"code":892,"language":569,"meta":101,"style":101},"{\n  \"role\": \"assistant\",\n  \"content\": null,\n  \"tool_calls\": [\n    {\n      \"id\": \"call_NkR3eNRohcWiYWCZBWhVem3a\",\n      \"type\": \"function\",\n      \"function\": {\n        \"name\": \"sendNumber\",\n        \"arguments\": \"{\\\"randomNumber\\\":354}\"\n      }\n    }\n  ]\n}\n",[56,894,895,899,909,920,928,932,944,955,963,974,995,1000,1005,1010],{"__ignoreMap":101},[105,896,897],{"class":107,"line":108},[105,898,576],{"class":118},[105,900,901,903,905,907],{"class":107,"line":115},[105,902,581],{"class":165},[105,904,584],{"class":118},[105,906,587],{"class":126},[105,908,383],{"class":118},[105,910,911,913,915,918],{"class":107,"line":185},[105,912,594],{"class":165},[105,914,584],{"class":118},[105,916,917],{"class":165},"null",[105,919,383],{"class":118},[105,921,922,925],{"class":107,"line":197},[105,923,924],{"class":165},"  \"tool_calls\"",[105,926,927],{"class":118},": [\n",[105,929,930],{"class":107,"line":204},[105,931,689],{"class":118},[105,933,934,937,939,942],{"class":107,"line":210},[105,935,936],{"class":165},"      \"id\"",[105,938,584],{"class":118},[105,940,941],{"class":126},"\"call_NkR3eNRohcWiYWCZBWhVem3a\"",[105,943,383],{"class":118},[105,945,946,949,951,953],{"class":107,"line":229},[105,947,948],{"class":165},"      \"type\"",[105,950,584],{"class":118},[105,952,769],{"class":126},[105,954,383],{"class":118},[105,956,957,960],{"class":107,"line":243},[105,958,959],{"class":165},"      \"function\"",[105,961,962],{"class":118},": {\n",[105,964,965,968,970,972],{"class":107,"line":248},[105,966,967],{"class":165},"        \"name\"",[105,969,584],{"class":118},[105,971,784],{"class":126},[105,973,383],{"class":118},[105,975,976,979,981,984,987,990,992],{"class":107,"line":254},[105,977,978],{"class":165},"        \"arguments\"",[105,980,584],{"class":118},[105,982,983],{"class":126},"\"{",[105,985,986],{"class":165},"\\\"",[105,988,989],{"class":126},"randomNumber",[105,991,986],{"class":165},[105,993,994],{"class":126},":354}\"\n",[105,996,997],{"class":107,"line":273},[105,998,999],{"class":118},"      }\n",[105,1001,1002],{"class":107,"line":290},[105,1003,1004],{"class":118},"    }\n",[105,1006,1007],{"class":107,"line":295},[105,1008,1009],{"class":118},"  ]\n",[105,1011,1012],{"class":107,"line":301},[105,1013,604],{"class":118},[15,1015,1016],{},"We modified two things:",[37,1018,1019,1035],{},[40,1020,1021,1022,1024,1025,1028,1029,1031,1032],{},"We declared a ",[67,1023,523],{}," in the call that the model can use. This function has a name, can have a description (which helps the model choose the function in certain cases), and parameters. The parameter type is always ",[56,1026,1027],{},"object"," and contains attributes, here ",[56,1030,989],{}," of type ",[56,1033,1034],{},"number",[40,1036,1037,1038,1041,1042,1045],{},"We added a ",[67,1039,1040],{},"system prompt"," telling the model to use the ",[56,1043,1044],{},"sendNumber"," function when it needs to send a number to the user.",[15,1047,1048,1049,1052,1053,1055],{},"In the response, the ",[56,1050,1051],{},"content"," attribute is ",[56,1054,917],{},", and we have a function call made by the model indicating which function to call and with which arguments. We can extract this:",[96,1057,1059],{"className":148,"code":1058,"language":150,"meta":101,"style":101},"let message = completion.choices[0].message;\nif (message.tool_calls) {\n  let fcall = message.tool_calls.find(\n    (tc) => tc.type === \"function\" && tc.function.name === \"sendNumber\"\n  );\n  let json = JSON.parse(fcall.function.arguments);\n  res.send({ n: json.randomNumber });\n}\n",[56,1060,1061,1075,1083,1101,1135,1140,1161,1170],{"__ignoreMap":101},[105,1062,1063,1065,1067,1069,1071,1073],{"class":107,"line":108},[105,1064,867],{"class":122},[105,1066,432],{"class":118},[105,1068,123],{"class":122},[105,1070,437],{"class":118},[105,1072,440],{"class":165},[105,1074,443],{"class":118},[105,1076,1077,1080],{"class":107,"line":115},[105,1078,1079],{"class":122},"if",[105,1081,1082],{"class":118}," (message.tool_calls) {\n",[105,1084,1085,1087,1090,1092,1095,1098],{"class":107,"line":185},[105,1086,429],{"class":122},[105,1088,1089],{"class":118}," fcall ",[105,1091,123],{"class":122},[105,1093,1094],{"class":118}," message.tool_calls.",[105,1096,1097],{"class":172},"find",[105,1099,1100],{"class":118},"(\n",[105,1102,1103,1106,1109,1112,1115,1118,1121,1124,1127,1130,1132],{"class":107,"line":197},[105,1104,1105],{"class":118},"    (",[105,1107,1108],{"class":327},"tc",[105,1110,1111],{"class":118},") ",[105,1113,1114],{"class":122},"=>",[105,1116,1117],{"class":118}," tc.type ",[105,1119,1120],{"class":122},"===",[105,1122,1123],{"class":126}," \"function\"",[105,1125,1126],{"class":122}," &&",[105,1128,1129],{"class":118}," tc.function.name ",[105,1131,1120],{"class":122},[105,1133,1134],{"class":126}," \"sendNumber\"\n",[105,1136,1137],{"class":107,"line":204},[105,1138,1139],{"class":118},"  );\n",[105,1141,1142,1144,1147,1149,1152,1155,1158],{"class":107,"line":210},[105,1143,429],{"class":122},[105,1145,1146],{"class":118}," json ",[105,1148,123],{"class":122},[105,1150,1151],{"class":165}," JSON",[105,1153,1154],{"class":118},".",[105,1156,1157],{"class":172},"parse",[105,1159,1160],{"class":118},"(fcall.function.arguments);\n",[105,1162,1163,1165,1167],{"class":107,"line":229},[105,1164,449],{"class":118},[105,1166,452],{"class":172},[105,1168,1169],{"class":118},"({ n: json.randomNumber });\n",[105,1171,1172],{"class":107,"line":243},[105,1173,604],{"class":118},[15,1175,1176],{},"This way we properly retrieve the expected number and can use it in our application.",[10,1178,1180],{"id":1179},"lets-have-some-fun","Let's have some fun",[15,1182,1183],{},"Let's modify the previous code to now ask ChatGPT to give interesting characteristics about the number it chose:",[96,1185,1187],{"className":148,"code":1186,"language":150,"meta":101,"style":101},"app.use(\"\u002Fnumber\", async function (req, res) {\n  const completion = await openai.chat.completions.create({\n    messages: [\n      {\n        role: \"system\",\n        content: \"To give a number to the user, use the sendNumber function\",\n      },\n      {\n        role: \"user\",\n        content:\n          \"Give me a random number between 1 and 1000 and explain why it's special\",\n      },\n    ],\n    model: \"gpt-4o\",\n    tools: [\n      {\n        type: \"function\",\n        function: {\n          name: \"sendNumber\",\n          description: \"send a number to the user\",\n          parameters: {\n            type: \"object\",\n            properties: {\n              randomNumber: {\n                type: \"number\",\n              },\n              reason: {\n                type: \"string\",\n              },\n            },\n          },\n        },\n      },\n    ],\n  });\n  let message = completion.choices[0].message;\n  if (message.tool_calls) {\n    let fcall = message.tool_calls.find(\n      (tc) => tc.type === \"function\" && tc.function.name === \"sendNumber\"\n    );\n    let json = JSON.parse(fcall.function.arguments);\n    res.send(json);\n  } else {\n    res.send({ error: \"no function call\" });\n  }\n});\n",[56,1188,1189,1216,1232,1236,1240,1248,1256,1260,1264,1272,1277,1284,1288,1292,1300,1305,1309,1318,1323,1332,1341,1346,1355,1360,1365,1374,1379,1384,1393,1397,1401,1405,1409,1414,1419,1424,1439,1447,1463,1489,1495,1512,1523,1535,1551,1557],{"__ignoreMap":101},[105,1190,1191,1193,1195,1197,1200,1202,1204,1206,1208,1210,1212,1214],{"class":107,"line":108},[105,1192,304],{"class":118},[105,1194,307],{"class":172},[105,1196,176],{"class":118},[105,1198,1199],{"class":126},"\"\u002Fnumber\"",[105,1201,315],{"class":118},[105,1203,318],{"class":122},[105,1205,321],{"class":122},[105,1207,324],{"class":118},[105,1209,328],{"class":327},[105,1211,315],{"class":118},[105,1213,333],{"class":327},[105,1215,336],{"class":118},[105,1217,1218,1220,1222,1224,1226,1228,1230],{"class":107,"line":115},[105,1219,342],{"class":122},[105,1221,345],{"class":165},[105,1223,169],{"class":122},[105,1225,350],{"class":122},[105,1227,353],{"class":118},[105,1229,356],{"class":172},[105,1231,359],{"class":118},[105,1233,1234],{"class":107,"line":185},[105,1235,365],{"class":118},[105,1237,1238],{"class":107,"line":197},[105,1239,371],{"class":118},[105,1241,1242,1244,1246],{"class":107,"line":204},[105,1243,377],{"class":118},[105,1245,697],{"class":126},[105,1247,383],{"class":118},[105,1249,1250,1252,1254],{"class":107,"line":210},[105,1251,389],{"class":118},[105,1253,707],{"class":126},[105,1255,383],{"class":118},[105,1257,1258],{"class":107,"line":229},[105,1259,400],{"class":118},[105,1261,1262],{"class":107,"line":243},[105,1263,371],{"class":118},[105,1265,1266,1268,1270],{"class":107,"line":248},[105,1267,377],{"class":118},[105,1269,380],{"class":126},[105,1271,383],{"class":118},[105,1273,1274],{"class":107,"line":254},[105,1275,1276],{"class":118},"        content:\n",[105,1278,1279,1282],{"class":107,"line":273},[105,1280,1281],{"class":126},"          \"Give me a random number between 1 and 1000 and explain why it's special\"",[105,1283,383],{"class":118},[105,1285,1286],{"class":107,"line":290},[105,1287,400],{"class":118},[105,1289,1290],{"class":107,"line":295},[105,1291,406],{"class":118},[105,1293,1294,1296,1298],{"class":107,"line":301},[105,1295,412],{"class":118},[105,1297,415],{"class":126},[105,1299,383],{"class":118},[105,1301,1302],{"class":107,"line":339},[105,1303,1304],{"class":118},"    tools: [\n",[105,1306,1307],{"class":107,"line":362},[105,1308,371],{"class":118},[105,1310,1311,1314,1316],{"class":107,"line":368},[105,1312,1313],{"class":118},"        type: ",[105,1315,769],{"class":126},[105,1317,383],{"class":118},[105,1319,1320],{"class":107,"line":374},[105,1321,1322],{"class":118},"        function: {\n",[105,1324,1325,1328,1330],{"class":107,"line":386},[105,1326,1327],{"class":118},"          name: ",[105,1329,784],{"class":126},[105,1331,383],{"class":118},[105,1333,1334,1337,1339],{"class":107,"line":397},[105,1335,1336],{"class":118},"          description: ",[105,1338,794],{"class":126},[105,1340,383],{"class":118},[105,1342,1343],{"class":107,"line":403},[105,1344,1345],{"class":118},"          parameters: {\n",[105,1347,1348,1351,1353],{"class":107,"line":409},[105,1349,1350],{"class":118},"            type: ",[105,1352,809],{"class":126},[105,1354,383],{"class":118},[105,1356,1357],{"class":107,"line":420},[105,1358,1359],{"class":118},"            properties: {\n",[105,1361,1362],{"class":107,"line":426},[105,1363,1364],{"class":118},"              randomNumber: {\n",[105,1366,1367,1370,1372],{"class":107,"line":446},[105,1368,1369],{"class":118},"                type: ",[105,1371,829],{"class":126},[105,1373,383],{"class":118},[105,1375,1376],{"class":107,"line":458},[105,1377,1378],{"class":118},"              },\n",[105,1380,1381],{"class":107,"line":464},[105,1382,1383],{"class":118},"              reason: {\n",[105,1385,1386,1388,1391],{"class":107,"line":469},[105,1387,1369],{"class":118},[105,1389,1390],{"class":126},"\"string\"",[105,1392,383],{"class":118},[105,1394,1395],{"class":107,"line":475},[105,1396,1378],{"class":118},[105,1398,1399],{"class":107,"line":502},[105,1400,836],{"class":118},[105,1402,1403],{"class":107,"line":529},[105,1404,841],{"class":118},[105,1406,1407],{"class":107,"line":555},[105,1408,846],{"class":118},[105,1410,1412],{"class":107,"line":1411},33,[105,1413,400],{"class":118},[105,1415,1417],{"class":107,"line":1416},34,[105,1418,406],{"class":118},[105,1420,1422],{"class":107,"line":1421},35,[105,1423,423],{"class":118},[105,1425,1427,1429,1431,1433,1435,1437],{"class":107,"line":1426},36,[105,1428,429],{"class":122},[105,1430,432],{"class":118},[105,1432,123],{"class":122},[105,1434,437],{"class":118},[105,1436,440],{"class":165},[105,1438,443],{"class":118},[105,1440,1442,1445],{"class":107,"line":1441},37,[105,1443,1444],{"class":122},"  if",[105,1446,1082],{"class":118},[105,1448,1450,1453,1455,1457,1459,1461],{"class":107,"line":1449},38,[105,1451,1452],{"class":122},"    let",[105,1454,1089],{"class":118},[105,1456,123],{"class":122},[105,1458,1094],{"class":118},[105,1460,1097],{"class":172},[105,1462,1100],{"class":118},[105,1464,1466,1469,1471,1473,1475,1477,1479,1481,1483,1485,1487],{"class":107,"line":1465},39,[105,1467,1468],{"class":118},"      (",[105,1470,1108],{"class":327},[105,1472,1111],{"class":118},[105,1474,1114],{"class":122},[105,1476,1117],{"class":118},[105,1478,1120],{"class":122},[105,1480,1123],{"class":126},[105,1482,1126],{"class":122},[105,1484,1129],{"class":118},[105,1486,1120],{"class":122},[105,1488,1134],{"class":126},[105,1490,1492],{"class":107,"line":1491},40,[105,1493,1494],{"class":118},"    );\n",[105,1496,1498,1500,1502,1504,1506,1508,1510],{"class":107,"line":1497},41,[105,1499,1452],{"class":122},[105,1501,1146],{"class":118},[105,1503,123],{"class":122},[105,1505,1151],{"class":165},[105,1507,1154],{"class":118},[105,1509,1157],{"class":172},[105,1511,1160],{"class":118},[105,1513,1515,1518,1520],{"class":107,"line":1514},42,[105,1516,1517],{"class":118},"    res.",[105,1519,452],{"class":172},[105,1521,1522],{"class":118},"(json);\n",[105,1524,1526,1529,1532],{"class":107,"line":1525},43,[105,1527,1528],{"class":118},"  } ",[105,1530,1531],{"class":122},"else",[105,1533,1534],{"class":118}," {\n",[105,1536,1538,1540,1542,1545,1548],{"class":107,"line":1537},44,[105,1539,1517],{"class":118},[105,1541,452],{"class":172},[105,1543,1544],{"class":118},"({ error: ",[105,1546,1547],{"class":126},"\"no function call\"",[105,1549,1550],{"class":118}," });\n",[105,1552,1554],{"class":107,"line":1553},45,[105,1555,1556],{"class":118},"  }\n",[105,1558,1560],{"class":107,"line":1559},46,[105,1561,461],{"class":118},[15,1563,1564,1565,1568],{},"The function the model will call now has two parameters: the number and a string in the ",[56,1566,1567],{},"reason"," attribute. The prompt has been modified to ask the model to explain why the chosen number is special.",[15,1570,1571],{},"Here are some responses:",[96,1573,1575],{"className":567,"code":1574,"language":569,"meta":101,"style":101},"[\n  {\n    \"randomNumber\": 622,\n    \"reason\": \"622 could be considered special because it is the number of resolutions (effective resolutions) passed by the United Nations General Assembly as of the end of 2020.\"\n  },\n  {\n    \"randomNumber\": 729,\n    \"reason\": \"It's the smallest number that can be expressed as the seventh power of another integer, specifically, 3^6.\"\n  },\n  {\n    \"randomNumber\": 317,\n    \"reason\": \"The number 317 is special because it's a prime number, which means it is greater than 1 and only divisible by 1 and itself.\"\n  }\n]\n",[56,1576,1577,1582,1587,1599,1609,1614,1618,1629,1638,1642,1646,1657,1666,1670],{"__ignoreMap":101},[105,1578,1579],{"class":107,"line":108},[105,1580,1581],{"class":118},"[\n",[105,1583,1584],{"class":107,"line":115},[105,1585,1586],{"class":118},"  {\n",[105,1588,1589,1592,1594,1597],{"class":107,"line":185},[105,1590,1591],{"class":165},"    \"randomNumber\"",[105,1593,584],{"class":118},[105,1595,1596],{"class":165},"622",[105,1598,383],{"class":118},[105,1600,1601,1604,1606],{"class":107,"line":197},[105,1602,1603],{"class":165},"    \"reason\"",[105,1605,584],{"class":118},[105,1607,1608],{"class":126},"\"622 could be considered special because it is the number of resolutions (effective resolutions) passed by the United Nations General Assembly as of the end of 2020.\"\n",[105,1610,1611],{"class":107,"line":204},[105,1612,1613],{"class":118},"  },\n",[105,1615,1616],{"class":107,"line":210},[105,1617,1586],{"class":118},[105,1619,1620,1622,1624,1627],{"class":107,"line":229},[105,1621,1591],{"class":165},[105,1623,584],{"class":118},[105,1625,1626],{"class":165},"729",[105,1628,383],{"class":118},[105,1630,1631,1633,1635],{"class":107,"line":243},[105,1632,1603],{"class":165},[105,1634,584],{"class":118},[105,1636,1637],{"class":126},"\"It's the smallest number that can be expressed as the seventh power of another integer, specifically, 3^6.\"\n",[105,1639,1640],{"class":107,"line":248},[105,1641,1613],{"class":118},[105,1643,1644],{"class":107,"line":254},[105,1645,1586],{"class":118},[105,1647,1648,1650,1652,1655],{"class":107,"line":273},[105,1649,1591],{"class":165},[105,1651,584],{"class":118},[105,1653,1654],{"class":165},"317",[105,1656,383],{"class":118},[105,1658,1659,1661,1663],{"class":107,"line":290},[105,1660,1603],{"class":165},[105,1662,584],{"class":118},[105,1664,1665],{"class":126},"\"The number 317 is special because it's a prime number, which means it is greater than 1 and only divisible by 1 and itself.\"\n",[105,1667,1668],{"class":107,"line":295},[105,1669,1556],{"class":118},[105,1671,1672],{"class":107,"line":301},[105,1673,1674],{"class":118},"]\n",[15,1676,1677],{},"These could be used for fun facts about a random number in an application.",[10,1679,1681],{"id":1680},"back-to-our-project","Back to our project",[15,1683,1684],{},"The Blue application facilitates daily aquarium management and offers among other things:",[37,1686,1687,1694,1700,1706],{},[40,1688,1689,1690,1693],{},"A ",[67,1691,1692],{},"measurement"," feature allowing daily recording of water temperature, pH, calcium, magnesium, phosphate levels...",[40,1695,1689,1696,1699],{},[67,1697,1698],{},"water change"," feature to calculate the amount of salt to add to the water being prepared to replace part of the aquarium water",[40,1701,1689,1702,1705],{},[67,1703,1704],{},"product addition"," feature to calculate the amount of a product to add to increase calcium concentration for example",[40,1707,1689,1708,1711],{},[67,1709,1710],{},"task management"," feature for one-time or recurring tasks",[15,1713,1714],{},"And many more possibilities, but we'll focus on these for now.",[15,1716,1717],{},"I want the model to have access to one or more functions for each need the application can fulfill, allowing it to perform actions.",[1719,1720,1722],"h3",{"id":1721},"automatic-measurement","Automatic measurement",[15,1724,1725],{},"Here is the function defined for measurement:",[96,1727,1729],{"className":567,"code":1728,"language":569,"meta":101,"style":101},"{\n  \"name\": \"takeMeasure\",\n  \"description\": \"Enregistre une mesure prise\",\n  \"parameters\": {\n    \"type\": \"object\",\n    \"properties\": {\n      \"element\": {\n        \"type\": \"string\",\n        \"enum\": [\n          \"calcium\", \"ph\", \"temperature\",\n          \"magnesium\", \"alkalinity\", \"phosphates\"\n        ]\n      },\n      \"value\": { \"type\": \"number\" },\n      \"unit\": {\n        \"type\": \"string\",\n        \"enum\": [\"mg\u002Fl\", \"ppm\", \"\", \"celcius\", \"farenheit\", \"dkh\", \"μg\u002Fl\"]\n      }\n    }\n  }\n}\n",[56,1730,1731,1735,1747,1759,1766,1777,1784,1791,1802,1809,1826,1841,1846,1850,1868,1875,1885,1927,1931,1935,1939],{"__ignoreMap":101},[105,1732,1733],{"class":107,"line":108},[105,1734,576],{"class":118},[105,1736,1737,1740,1742,1745],{"class":107,"line":115},[105,1738,1739],{"class":165},"  \"name\"",[105,1741,584],{"class":118},[105,1743,1744],{"class":126},"\"takeMeasure\"",[105,1746,383],{"class":118},[105,1748,1749,1752,1754,1757],{"class":107,"line":185},[105,1750,1751],{"class":165},"  \"description\"",[105,1753,584],{"class":118},[105,1755,1756],{"class":126},"\"Enregistre une mesure prise\"",[105,1758,383],{"class":118},[105,1760,1761,1764],{"class":107,"line":197},[105,1762,1763],{"class":165},"  \"parameters\"",[105,1765,962],{"class":118},[105,1767,1768,1771,1773,1775],{"class":107,"line":204},[105,1769,1770],{"class":165},"    \"type\"",[105,1772,584],{"class":118},[105,1774,809],{"class":126},[105,1776,383],{"class":118},[105,1778,1779,1782],{"class":107,"line":210},[105,1780,1781],{"class":165},"    \"properties\"",[105,1783,962],{"class":118},[105,1785,1786,1789],{"class":107,"line":229},[105,1787,1788],{"class":165},"      \"element\"",[105,1790,962],{"class":118},[105,1792,1793,1796,1798,1800],{"class":107,"line":243},[105,1794,1795],{"class":165},"        \"type\"",[105,1797,584],{"class":118},[105,1799,1390],{"class":126},[105,1801,383],{"class":118},[105,1803,1804,1807],{"class":107,"line":248},[105,1805,1806],{"class":165},"        \"enum\"",[105,1808,927],{"class":118},[105,1810,1811,1814,1816,1819,1821,1824],{"class":107,"line":254},[105,1812,1813],{"class":126},"          \"calcium\"",[105,1815,315],{"class":118},[105,1817,1818],{"class":126},"\"ph\"",[105,1820,315],{"class":118},[105,1822,1823],{"class":126},"\"temperature\"",[105,1825,383],{"class":118},[105,1827,1828,1831,1833,1836,1838],{"class":107,"line":273},[105,1829,1830],{"class":126},"          \"magnesium\"",[105,1832,315],{"class":118},[105,1834,1835],{"class":126},"\"alkalinity\"",[105,1837,315],{"class":118},[105,1839,1840],{"class":126},"\"phosphates\"\n",[105,1842,1843],{"class":107,"line":290},[105,1844,1845],{"class":118},"        ]\n",[105,1847,1848],{"class":107,"line":295},[105,1849,400],{"class":118},[105,1851,1852,1855,1858,1861,1863,1865],{"class":107,"line":301},[105,1853,1854],{"class":165},"      \"value\"",[105,1856,1857],{"class":118},": { ",[105,1859,1860],{"class":165},"\"type\"",[105,1862,584],{"class":118},[105,1864,829],{"class":126},[105,1866,1867],{"class":118}," },\n",[105,1869,1870,1873],{"class":107,"line":339},[105,1871,1872],{"class":165},"      \"unit\"",[105,1874,962],{"class":118},[105,1876,1877,1879,1881,1883],{"class":107,"line":362},[105,1878,1795],{"class":165},[105,1880,584],{"class":118},[105,1882,1390],{"class":126},[105,1884,383],{"class":118},[105,1886,1887,1889,1892,1895,1897,1900,1902,1905,1907,1910,1912,1915,1917,1920,1922,1925],{"class":107,"line":368},[105,1888,1806],{"class":165},[105,1890,1891],{"class":118},": [",[105,1893,1894],{"class":126},"\"mg\u002Fl\"",[105,1896,315],{"class":118},[105,1898,1899],{"class":126},"\"ppm\"",[105,1901,315],{"class":118},[105,1903,1904],{"class":126},"\"\"",[105,1906,315],{"class":118},[105,1908,1909],{"class":126},"\"celcius\"",[105,1911,315],{"class":118},[105,1913,1914],{"class":126},"\"farenheit\"",[105,1916,315],{"class":118},[105,1918,1919],{"class":126},"\"dkh\"",[105,1921,315],{"class":118},[105,1923,1924],{"class":126},"\"μg\u002Fl\"",[105,1926,1674],{"class":118},[105,1928,1929],{"class":107,"line":374},[105,1930,999],{"class":118},[105,1932,1933],{"class":107,"line":386},[105,1934,1004],{"class":118},[105,1936,1937],{"class":107,"line":397},[105,1938,1556],{"class":118},[105,1940,1941],{"class":107,"line":403},[105,1942,604],{"class":118},[15,1944,1945],{},"I modify the code to indicate that the user's question is sent in the request, which allows me to test more easily. The request becomes a POST request with a body:",[96,1947,1949],{"className":148,"code":1948,"language":150,"meta":101,"style":101},"app.use(\"\u002Fblue\", async function (req, res) {\n  let body = req.body;\n  const completion = await openai.chat.completions.create({\n    messages: [\n      {\n        role: \"system\",\n        content:\n          \"Tu as accès à certaines fonctionnalités d'une application mobile de gestion d'aquarium récifal. Utilise les fonctions fournies pour répondre et interagir avec l'utilisateur. L'aquarium de l'utilisateur fait 700L\",\n      },\n      {\n        role: \"user\",\n        content: body.question,\n      },\n    ],\n    model: \"gpt-4o\",\n    tools: [\n      {\n        type: \"function\",\n        function: {\n          \u002F\u002F the takeMeasure function\n        },\n      },\n    ],\n  });\n});\n",[56,1950,1951,1978,1990,2006,2010,2014,2022,2026,2033,2037,2041,2049,2054,2058,2062,2070,2074,2078,2086,2090,2095,2099,2103,2107,2111],{"__ignoreMap":101},[105,1952,1953,1955,1957,1959,1962,1964,1966,1968,1970,1972,1974,1976],{"class":107,"line":108},[105,1954,304],{"class":118},[105,1956,307],{"class":172},[105,1958,176],{"class":118},[105,1960,1961],{"class":126},"\"\u002Fblue\"",[105,1963,315],{"class":118},[105,1965,318],{"class":122},[105,1967,321],{"class":122},[105,1969,324],{"class":118},[105,1971,328],{"class":327},[105,1973,315],{"class":118},[105,1975,333],{"class":327},[105,1977,336],{"class":118},[105,1979,1980,1982,1985,1987],{"class":107,"line":115},[105,1981,429],{"class":122},[105,1983,1984],{"class":118}," body ",[105,1986,123],{"class":122},[105,1988,1989],{"class":118}," req.body;\n",[105,1991,1992,1994,1996,1998,2000,2002,2004],{"class":107,"line":185},[105,1993,342],{"class":122},[105,1995,345],{"class":165},[105,1997,169],{"class":122},[105,1999,350],{"class":122},[105,2001,353],{"class":118},[105,2003,356],{"class":172},[105,2005,359],{"class":118},[105,2007,2008],{"class":107,"line":197},[105,2009,365],{"class":118},[105,2011,2012],{"class":107,"line":204},[105,2013,371],{"class":118},[105,2015,2016,2018,2020],{"class":107,"line":210},[105,2017,377],{"class":118},[105,2019,697],{"class":126},[105,2021,383],{"class":118},[105,2023,2024],{"class":107,"line":229},[105,2025,1276],{"class":118},[105,2027,2028,2031],{"class":107,"line":243},[105,2029,2030],{"class":126},"          \"Tu as accès à certaines fonctionnalités d'une application mobile de gestion d'aquarium récifal. Utilise les fonctions fournies pour répondre et interagir avec l'utilisateur. L'aquarium de l'utilisateur fait 700L\"",[105,2032,383],{"class":118},[105,2034,2035],{"class":107,"line":248},[105,2036,400],{"class":118},[105,2038,2039],{"class":107,"line":254},[105,2040,371],{"class":118},[105,2042,2043,2045,2047],{"class":107,"line":273},[105,2044,377],{"class":118},[105,2046,380],{"class":126},[105,2048,383],{"class":118},[105,2050,2051],{"class":107,"line":290},[105,2052,2053],{"class":118},"        content: body.question,\n",[105,2055,2056],{"class":107,"line":295},[105,2057,400],{"class":118},[105,2059,2060],{"class":107,"line":301},[105,2061,406],{"class":118},[105,2063,2064,2066,2068],{"class":107,"line":339},[105,2065,412],{"class":118},[105,2067,415],{"class":126},[105,2069,383],{"class":118},[105,2071,2072],{"class":107,"line":362},[105,2073,1304],{"class":118},[105,2075,2076],{"class":107,"line":368},[105,2077,371],{"class":118},[105,2079,2080,2082,2084],{"class":107,"line":374},[105,2081,1313],{"class":118},[105,2083,769],{"class":126},[105,2085,383],{"class":118},[105,2087,2088],{"class":107,"line":386},[105,2089,1322],{"class":118},[105,2091,2092],{"class":107,"line":397},[105,2093,2094],{"class":111},"          \u002F\u002F the takeMeasure function\n",[105,2096,2097],{"class":107,"line":403},[105,2098,846],{"class":118},[105,2100,2101],{"class":107,"line":409},[105,2102,400],{"class":118},[105,2104,2105],{"class":107,"line":420},[105,2106,406],{"class":118},[105,2108,2109],{"class":107,"line":426},[105,2110,423],{"class":118},[105,2112,2113],{"class":107,"line":446},[105,2114,461],{"class":118},[15,2116,2117],{},"When the user sends \"Mon thermomètre indique 24\" (My thermometer reads 24), the model responds:",[96,2119,2121],{"className":567,"code":2120,"language":569,"meta":101,"style":101},"{\n  \"name\": \"takeMeasure\",\n  \"arguments\": {\n    \"element\": \"temperature\",\n    \"value\": 24,\n    \"unit\": \"celcius\"\n  }\n}\n",[56,2122,2123,2127,2137,2144,2155,2167,2177,2181],{"__ignoreMap":101},[105,2124,2125],{"class":107,"line":108},[105,2126,576],{"class":118},[105,2128,2129,2131,2133,2135],{"class":107,"line":115},[105,2130,1739],{"class":165},[105,2132,584],{"class":118},[105,2134,1744],{"class":126},[105,2136,383],{"class":118},[105,2138,2139,2142],{"class":107,"line":185},[105,2140,2141],{"class":165},"  \"arguments\"",[105,2143,962],{"class":118},[105,2145,2146,2149,2151,2153],{"class":107,"line":197},[105,2147,2148],{"class":165},"    \"element\"",[105,2150,584],{"class":118},[105,2152,1823],{"class":126},[105,2154,383],{"class":118},[105,2156,2157,2160,2162,2165],{"class":107,"line":204},[105,2158,2159],{"class":165},"    \"value\"",[105,2161,584],{"class":118},[105,2163,2164],{"class":165},"24",[105,2166,383],{"class":118},[105,2168,2169,2172,2174],{"class":107,"line":210},[105,2170,2171],{"class":165},"    \"unit\"",[105,2173,584],{"class":118},[105,2175,2176],{"class":126},"\"celcius\"\n",[105,2178,2179],{"class":107,"line":229},[105,2180,1556],{"class":118},[105,2182,2183],{"class":107,"line":243},[105,2184,604],{"class":118},[15,2186,2187],{},"This allows automatically recording the latest aquarium temperature. The application controls the unit and stores it to perform conversions.",[15,2189,2190],{},"The user now says \"Le calcium est à 410\" (Calcium is at 410), the model responds:",[96,2192,2194],{"className":567,"code":2193,"language":569,"meta":101,"style":101},"{\n  \"name\": \"takeMeasure\",\n  \"arguments\": {\n    \"element\": \"calcium\",\n    \"value\": 410,\n    \"unit\": \"ppm\"\n  }\n}\n",[56,2195,2196,2200,2210,2216,2227,2238,2247,2251],{"__ignoreMap":101},[105,2197,2198],{"class":107,"line":108},[105,2199,576],{"class":118},[105,2201,2202,2204,2206,2208],{"class":107,"line":115},[105,2203,1739],{"class":165},[105,2205,584],{"class":118},[105,2207,1744],{"class":126},[105,2209,383],{"class":118},[105,2211,2212,2214],{"class":107,"line":185},[105,2213,2141],{"class":165},[105,2215,962],{"class":118},[105,2217,2218,2220,2222,2225],{"class":107,"line":197},[105,2219,2148],{"class":165},[105,2221,584],{"class":118},[105,2223,2224],{"class":126},"\"calcium\"",[105,2226,383],{"class":118},[105,2228,2229,2231,2233,2236],{"class":107,"line":204},[105,2230,2159],{"class":165},[105,2232,584],{"class":118},[105,2234,2235],{"class":165},"410",[105,2237,383],{"class":118},[105,2239,2240,2242,2244],{"class":107,"line":210},[105,2241,2171],{"class":165},[105,2243,584],{"class":118},[105,2245,2246],{"class":126},"\"ppm\"\n",[105,2248,2249],{"class":107,"line":229},[105,2250,1556],{"class":118},[105,2252,2253],{"class":107,"line":243},[105,2254,604],{"class":118},[1719,2256,2258],{"id":2257},"water-changes","Water changes",[15,2260,2261],{},"Let's now add a function allowing the model to ask the application to launch a water change:",[96,2263,2265],{"className":567,"code":2264,"language":569,"meta":101,"style":101},"{\n  \"name\": \"calcWaterChange\",\n  \"description\": \"Lance le calcul d'un changement d'eau si tu ne sais pas quel volume d'eau utiliser, calcule 15% du volume de l'aquarium\",\n  \"parameters\": {\n    \"type\": \"object\",\n    \"properties\": {\n      \"volume\": {\n        \"type\": \"number\",\n        \"description\": \"Volume d'eau à changer\"\n      }\n    }\n  }\n}\n",[56,2266,2267,2271,2282,2293,2299,2309,2315,2322,2332,2342,2346,2350,2354],{"__ignoreMap":101},[105,2268,2269],{"class":107,"line":108},[105,2270,576],{"class":118},[105,2272,2273,2275,2277,2280],{"class":107,"line":115},[105,2274,1739],{"class":165},[105,2276,584],{"class":118},[105,2278,2279],{"class":126},"\"calcWaterChange\"",[105,2281,383],{"class":118},[105,2283,2284,2286,2288,2291],{"class":107,"line":185},[105,2285,1751],{"class":165},[105,2287,584],{"class":118},[105,2289,2290],{"class":126},"\"Lance le calcul d'un changement d'eau si tu ne sais pas quel volume d'eau utiliser, calcule 15% du volume de l'aquarium\"",[105,2292,383],{"class":118},[105,2294,2295,2297],{"class":107,"line":197},[105,2296,1763],{"class":165},[105,2298,962],{"class":118},[105,2300,2301,2303,2305,2307],{"class":107,"line":204},[105,2302,1770],{"class":165},[105,2304,584],{"class":118},[105,2306,809],{"class":126},[105,2308,383],{"class":118},[105,2310,2311,2313],{"class":107,"line":210},[105,2312,1781],{"class":165},[105,2314,962],{"class":118},[105,2316,2317,2320],{"class":107,"line":229},[105,2318,2319],{"class":165},"      \"volume\"",[105,2321,962],{"class":118},[105,2323,2324,2326,2328,2330],{"class":107,"line":243},[105,2325,1795],{"class":165},[105,2327,584],{"class":118},[105,2329,829],{"class":126},[105,2331,383],{"class":118},[105,2333,2334,2337,2339],{"class":107,"line":248},[105,2335,2336],{"class":165},"        \"description\"",[105,2338,584],{"class":118},[105,2340,2341],{"class":126},"\"Volume d'eau à changer\"\n",[105,2343,2344],{"class":107,"line":254},[105,2345,999],{"class":118},[105,2347,2348],{"class":107,"line":273},[105,2349,1004],{"class":118},[105,2351,2352],{"class":107,"line":290},[105,2353,1556],{"class":118},[105,2355,2356],{"class":107,"line":295},[105,2357,604],{"class":118},[15,2359,2360],{},"The user says \"Lance un changement d'eau de 10%\" (Launch a 10% water change), the model responds:",[96,2362,2364],{"className":567,"code":2363,"language":569,"meta":101,"style":101},"{\n  \"name\": \"calcWaterChange\",\n  \"arguments\": {\n    \"volume\": 70\n  }\n}\n",[56,2365,2366,2370,2380,2386,2396,2400],{"__ignoreMap":101},[105,2367,2368],{"class":107,"line":108},[105,2369,576],{"class":118},[105,2371,2372,2374,2376,2378],{"class":107,"line":115},[105,2373,1739],{"class":165},[105,2375,584],{"class":118},[105,2377,2279],{"class":126},[105,2379,383],{"class":118},[105,2381,2382,2384],{"class":107,"line":185},[105,2383,2141],{"class":165},[105,2385,962],{"class":118},[105,2387,2388,2391,2393],{"class":107,"line":197},[105,2389,2390],{"class":165},"    \"volume\"",[105,2392,584],{"class":118},[105,2394,2395],{"class":165},"70\n",[105,2397,2398],{"class":107,"line":204},[105,2399,1556],{"class":118},[105,2401,2402],{"class":107,"line":210},[105,2403,604],{"class":118},[15,2405,2406,2407,2411],{},"We indicated in the system prompt information about the user's aquarium (",[2408,2409,2410],"em",{},"L'aquarium de l'utilisateur fait 700L","). So when the user asks to change 10% of their water volume, the model calculates the amount of water to change and calls the function.",[15,2413,2414],{},"If the user simply says \"Lance un changement d'eau\" (Launch a water change), the model responds:",[96,2416,2418],{"className":567,"code":2417,"language":569,"meta":101,"style":101},"{\n  \"name\": \"calcWaterChange\",\n  \"arguments\": {\n    \"volume\": 105\n  }\n}\n",[56,2419,2420,2424,2434,2440,2449,2453],{"__ignoreMap":101},[105,2421,2422],{"class":107,"line":108},[105,2423,576],{"class":118},[105,2425,2426,2428,2430,2432],{"class":107,"line":115},[105,2427,1739],{"class":165},[105,2429,584],{"class":118},[105,2431,2279],{"class":126},[105,2433,383],{"class":118},[105,2435,2436,2438],{"class":107,"line":185},[105,2437,2141],{"class":165},[105,2439,962],{"class":118},[105,2441,2442,2444,2446],{"class":107,"line":197},[105,2443,2390],{"class":165},[105,2445,584],{"class":118},[105,2447,2448],{"class":165},"105\n",[105,2450,2451],{"class":107,"line":204},[105,2452,1556],{"class":118},[105,2454,2455],{"class":107,"line":210},[105,2456,604],{"class":118},[15,2458,2459],{},"Because we indicated in the function description that if no volume is specified by the user, it should calculate 15% of the user's aquarium volume.",[10,2461,2463],{"id":2462},"whats-next","What's next",[15,2465,2466],{},"Here are other functions I provide to meet the needs of the features presented:",[96,2468,2470],{"className":567,"code":2469,"language":569,"meta":101,"style":101},"{\n  \"name\": \"calcAddition\",\n  \"description\": \"Lance le calcul d'un ajout de produit\",\n  \"parameters\": {\n    \"type\": \"object\",\n    \"properties\": {\n      \"element\": {\n        \"type\": \"string\",\n        \"enum\": [\n          \"calcium\", \"ph\", \"temperature\",\n          \"magnesium\", \"alkalinity\", \"phosphates\"\n        ]\n      }\n    }\n  }\n}\n",[56,2471,2472,2476,2487,2498,2504,2514,2520,2526,2536,2542,2556,2568,2572,2576,2580,2584],{"__ignoreMap":101},[105,2473,2474],{"class":107,"line":108},[105,2475,576],{"class":118},[105,2477,2478,2480,2482,2485],{"class":107,"line":115},[105,2479,1739],{"class":165},[105,2481,584],{"class":118},[105,2483,2484],{"class":126},"\"calcAddition\"",[105,2486,383],{"class":118},[105,2488,2489,2491,2493,2496],{"class":107,"line":185},[105,2490,1751],{"class":165},[105,2492,584],{"class":118},[105,2494,2495],{"class":126},"\"Lance le calcul d'un ajout de produit\"",[105,2497,383],{"class":118},[105,2499,2500,2502],{"class":107,"line":197},[105,2501,1763],{"class":165},[105,2503,962],{"class":118},[105,2505,2506,2508,2510,2512],{"class":107,"line":204},[105,2507,1770],{"class":165},[105,2509,584],{"class":118},[105,2511,809],{"class":126},[105,2513,383],{"class":118},[105,2515,2516,2518],{"class":107,"line":210},[105,2517,1781],{"class":165},[105,2519,962],{"class":118},[105,2521,2522,2524],{"class":107,"line":229},[105,2523,1788],{"class":165},[105,2525,962],{"class":118},[105,2527,2528,2530,2532,2534],{"class":107,"line":243},[105,2529,1795],{"class":165},[105,2531,584],{"class":118},[105,2533,1390],{"class":126},[105,2535,383],{"class":118},[105,2537,2538,2540],{"class":107,"line":248},[105,2539,1806],{"class":165},[105,2541,927],{"class":118},[105,2543,2544,2546,2548,2550,2552,2554],{"class":107,"line":254},[105,2545,1813],{"class":126},[105,2547,315],{"class":118},[105,2549,1818],{"class":126},[105,2551,315],{"class":118},[105,2553,1823],{"class":126},[105,2555,383],{"class":118},[105,2557,2558,2560,2562,2564,2566],{"class":107,"line":273},[105,2559,1830],{"class":126},[105,2561,315],{"class":118},[105,2563,1835],{"class":126},[105,2565,315],{"class":118},[105,2567,1840],{"class":126},[105,2569,2570],{"class":107,"line":290},[105,2571,1845],{"class":118},[105,2573,2574],{"class":107,"line":295},[105,2575,999],{"class":118},[105,2577,2578],{"class":107,"line":301},[105,2579,1004],{"class":118},[105,2581,2582],{"class":107,"line":339},[105,2583,1556],{"class":118},[105,2585,2586],{"class":107,"line":362},[105,2587,604],{"class":118},[96,2589,2591],{"className":567,"code":2590,"language":569,"meta":101,"style":101},"{\n  \"name\": \"getMeasure\",\n  \"description\": \"Récupère la valeur de la dernière mesure prise pour un élément. Utilise cette fonction pour connaitre une valeur\",\n  \"parameters\": {\n    \"type\": \"object\",\n    \"properties\": {\n      \"element\": {\n        \"type\": \"string\",\n        \"enum\": [\n          \"calcium\", \"ph\", \"temperature\",\n          \"magnesium\", \"alkalinity\", \"phosphates\"\n        ]\n      }\n    }\n  }\n}\n",[56,2592,2593,2597,2608,2619,2625,2635,2641,2647,2657,2663,2677,2689,2693,2697,2701,2705],{"__ignoreMap":101},[105,2594,2595],{"class":107,"line":108},[105,2596,576],{"class":118},[105,2598,2599,2601,2603,2606],{"class":107,"line":115},[105,2600,1739],{"class":165},[105,2602,584],{"class":118},[105,2604,2605],{"class":126},"\"getMeasure\"",[105,2607,383],{"class":118},[105,2609,2610,2612,2614,2617],{"class":107,"line":185},[105,2611,1751],{"class":165},[105,2613,584],{"class":118},[105,2615,2616],{"class":126},"\"Récupère la valeur de la dernière mesure prise pour un élément. Utilise cette fonction pour connaitre une valeur\"",[105,2618,383],{"class":118},[105,2620,2621,2623],{"class":107,"line":197},[105,2622,1763],{"class":165},[105,2624,962],{"class":118},[105,2626,2627,2629,2631,2633],{"class":107,"line":204},[105,2628,1770],{"class":165},[105,2630,584],{"class":118},[105,2632,809],{"class":126},[105,2634,383],{"class":118},[105,2636,2637,2639],{"class":107,"line":210},[105,2638,1781],{"class":165},[105,2640,962],{"class":118},[105,2642,2643,2645],{"class":107,"line":229},[105,2644,1788],{"class":165},[105,2646,962],{"class":118},[105,2648,2649,2651,2653,2655],{"class":107,"line":243},[105,2650,1795],{"class":165},[105,2652,584],{"class":118},[105,2654,1390],{"class":126},[105,2656,383],{"class":118},[105,2658,2659,2661],{"class":107,"line":248},[105,2660,1806],{"class":165},[105,2662,927],{"class":118},[105,2664,2665,2667,2669,2671,2673,2675],{"class":107,"line":254},[105,2666,1813],{"class":126},[105,2668,315],{"class":118},[105,2670,1818],{"class":126},[105,2672,315],{"class":118},[105,2674,1823],{"class":126},[105,2676,383],{"class":118},[105,2678,2679,2681,2683,2685,2687],{"class":107,"line":273},[105,2680,1830],{"class":126},[105,2682,315],{"class":118},[105,2684,1835],{"class":126},[105,2686,315],{"class":118},[105,2688,1840],{"class":126},[105,2690,2691],{"class":107,"line":290},[105,2692,1845],{"class":118},[105,2694,2695],{"class":107,"line":295},[105,2696,999],{"class":118},[105,2698,2699],{"class":107,"line":301},[105,2700,1004],{"class":118},[105,2702,2703],{"class":107,"line":339},[105,2704,1556],{"class":118},[105,2706,2707],{"class":107,"line":362},[105,2708,604],{"class":118},[15,2710,2711,2712,2715,2716,1154],{},"This way the model can decide to call the ",[56,2713,2714],{},"getMeasure"," function if it needs information to answer the user. If the user asks whether their calcium is too high, the model can choose to call ",[56,2717,2714],{},[15,2719,2720,2721,2724,2725,2728],{},"In my code, I have two types of functions: those that ",[67,2722,2723],{},"trigger an event"," (recording a measurement, launching a water change or addition calculation), and those that ",[67,2726,2727],{},"fetch information"," for the model. In the second case, the model is called again with the previous context (the message history and the function result).",[15,2730,2731],{},"More complex interactions with the model will be covered in another post.",[15,2733,2734],{},"The user can also ask questions about their aquarium, about fish species, whether they would be suitable - in these cases the model doesn't use a function and the response is presented to the user directly.",[15,2736,2737],{},"This type of interaction is truly powerful, provides real added value for the user and produces a spectacular effect. However, for interactions to be smooth, they should be done with voice rather than text. The application being very ergonomic, features are at your fingertips and model interaction isn't necessary to trigger actions. On the other hand, voice interaction, especially for measurements, allows hands-free use of the application, which is a real advantage for users when they have their hands in the water.",[2739,2740,2741],"style",{},"html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html pre.shiki code .snl16, html code.shiki .snl16{--shiki-default:#F97583}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}html pre.shiki code .svObZ, html code.shiki .svObZ{--shiki-default:#B392F0}html pre.shiki code .s9osk, html code.shiki .s9osk{--shiki-default:#FFAB70}",{"title":101,"searchDepth":115,"depth":115,"links":2743},[2744,2745,2746,2747,2748,2752],{"id":12,"depth":115,"text":13},{"id":83,"depth":115,"text":84},{"id":645,"depth":115,"text":646},{"id":1179,"depth":115,"text":1180},{"id":1680,"depth":115,"text":1681,"children":2749},[2750,2751],{"id":1721,"depth":185,"text":1722},{"id":2257,"depth":185,"text":2258},{"id":2462,"depth":115,"text":2463},"2024-05-20","How to efficiently interface your application with ChatGPT, use functions and retrieve triggerable decisions in your app.","md",{},"\u002Fblog\u002Fen\u002Frevolutionize-your-app-with-chatgpt",{"title":5,"description":2754},"blog\u002Fen\u002Frevolutionize-your-app-with-chatgpt",[2761,2762,2763],"OpenAI","Artificial Intelligence","Blue","revolutionnez-votre-app-avec-chatgpt","3MlOC_DS4ln5siUepAQPVYtlryPfAt7Fbx1f6uamg7w",1774359325135]