// Ozone AI Chat module for Active NPC by Brettson - Ghost writer for Spax Orion // Common sense is not included with this software and must be supplied by end user. // make sure ollama is running with the host variable enabled and that your chosen // model has been pulled from the repo. Compiled on XEngine for legacy application, // not everyone wants to use YEngine yet! // // You will need to change values in the configuration AND in the commented areas of the script below. // //Configuration string OLLAMA_URL = "http://127.0.0.1:11434/api/chat"; //you can use your direct ip address and port or domain name string MODEL_NAME = "downloaded-model-name"; string SYSTEM_PROMPT = "You are a flippant assistant, your responses will be rude, dismissive, detailed and condescending."; //You are not done yet, change some values where commented below... // Memory Variables list chat_history = []; integer MAX_HISTORY = 10; // User + AI exchanges key req; // Compatible search-and-replace for older LSL/OpenSim environments string strReplace(string str, string search, string replace) { return llDumpList2String(llParseStringKeepNulls(str, [search], []), replace); } string escapeJson(string input) { input = strReplace(input, "\\", "\\\\"); input = strReplace(input, "\"", "\\\""); input = strReplace(input, "\n", "\\n"); return input; } string buildChatJson() { string json = "[{\"role\": \"system\", \"content\": \"" + escapeJson(SYSTEM_PROMPT) + "\"}"; integer i; for (i = 0; i < llGetListLength(chat_history); i++) { json += "," + llList2String(chat_history, i); } return json + "]"; } default { state_entry() { llListen(0, "", llGetOwner(), ""); // change alice (it must appear twice) to the name you want. // chosen npc lets you know this code is working. llRegionSay(1968, "! 0000-0000-0000-0000 alice alice say READY"); // scroll down, another line to change... } on_rez(integer start_param) { llResetScript(); } listen(integer channel, string name, key id, string msg) { string user_json = "{\"role\": \"user\", \"content\": \"" + escapeJson(msg) + "\"}"; chat_history += [user_json]; string body = "{\"model\": \"" + MODEL_NAME + "\", " + "\"messages\": " + buildChatJson() + ", " + "\"stream\": false}"; req = llHTTPRequest(OLLAMA_URL, [HTTP_METHOD, "POST", HTTP_MIMETYPE, "application/json"], body); } http_response(key id, integer status, list meta, string body) { if (id != req) return; if (status == 200) { string reply = llJsonGetValue(body, ["message", "content"]); string ai_json = "{\"role\": \"assistant\", \"content\": \"" + escapeJson(reply) + "\"}"; chat_history += [ai_json]; while (llGetListLength(chat_history) > MAX_HISTORY) { chat_history = llDeleteSubList(chat_history, 0, 0); } // change 1968 to the channel of your Active NPC listener // change alice (it must appear twice) to the name you want. llRegionSay(1968, "! 0000-0000-0000-0000 alice alice say "+reply); } else { //when this happens you know the server did not get your request. llSay(0, "Hmmm... .. ."); //change this to the error message you want. } } }