Note Card[edit]
ChatGPT_API_Key[edit]
sk-##########################################
ChatGPT_Model[edit]
gpt-4-turbo
ChatGPT_Charactor[edit]
貴方は美術館の説明員です.
美術の質問以外については答えてはいけません.
答えは日本語で答えます.
NSL ChatGPT for OpenSimulator[edit]
// NSL ChatGPT for OpenSimulator v1.3.1
//
integer command_channel = 0;
integer listen_hdl = 0;
integer say_bufsize = 320; // < 1023バイト以下での UTF-8(3Byte) の文字数
float gap_time = 4.0;
integer time_count = 0;
// ChatGPT API のエンドポイント
string api_url = "https://api.openai.com/v1/chat/completions";
// ChatGPT API の変数
string api_key = "";
string api_model = "";
string api_chara = "";
// Note Card
string chara_notecard_name = "ChatGPT_Charactor";
string model_notecard_name = "ChatGPT_Model";
string gptkey_notecard_name = "ChatGPT_API_Key";
key chara_notecard_key = NULL_KEY;
key model_notecard_key = NULL_KEY;
key gptkey_notecard_key = NULL_KEY;
integer chara_notecard_line = 0;
integer model_notecard_line = 0;
integer gptkey_notecard_line = 0;
string chara_notecard = "";
string model_notecard = "";
string gptkey_notecard = "";
// ChatGPT API の JSON データのテンプレート.記載されていないパラメータはデフォルト値
string json_templ = "{
\"model\": \"\",
\"user\": \"\",
\"messages\":[
{
\"role\": \"system\",
\"content\": \"\"
},
{
\"role\": \"user\",
\"content\": \"\"
}
],
\"stream\": false
}";
//
key user_key = NULL_KEY;
key npc_key = NULL_KEY;
string user_name = "";
// ノートカードから最初の一行を読み込む
key read_notecard_first(string notecard_name)
{
if (llGetInventoryType(notecard_name)==INVENTORY_NOTECARD) {
key notecard_key = llGetNotecardLine(notecard_name, 0);
return notecard_key;
}
return NULL_KEY;
}
// 全てのノートカードを読み込む
read_notecards()
{
chara_notecard = "";
model_notecard = "";
gptkey_notecard = "";
chara_notecard_key = read_notecard_first(chara_notecard_name);
gptkey_notecard_key = read_notecard_first(gptkey_notecard_name);
model_notecard_key = read_notecard_first(model_notecard_name);
}
// ChatGPTの APIに _messageを送信する.
request_gpt_api(string _message)
{
string _json_body = "";
_json_body = llJsonSetValue(json_templ, ["model"], api_model);
_json_body = llJsonSetValue(_json_body, ["user"], user_key);
_json_body = llJsonSetValue(_json_body, ["messages", 0, "content"], api_chara);
_json_body = llJsonSetValue(_json_body, ["messages", 1, "content"], _message);
//llSay(0, _json_body);
llHTTPRequest(api_url,
[
HTTP_MIMETYPE, "application/json",
HTTP_METHOD, "POST",
HTTP_BODY_MAXLENGTH, 16384,
//HTTP_ACCEPT, "application/json",
HTTP_CUSTOM_HEADER, "Authorization", "Bearer " + api_key
],
_json_body
);
}
start_conversation(string _name)
{
//llSay(0, "Start Conversation");
request_gpt_api("こんにちは.私は " + _name + " です");
llListen(0, "", NULL_KEY, "");
}
short_conversation(string _message)
{
if (npc_key == NULL_KEY) {
llRegionSayTo(user_key, 0, _message);
}
else {
osNpcSayTo(npc_key, user_key, 0, _message);
}
}
stop_conversation()
{
string _message = "バイバイ.";
short_conversation(_message);
}
init_state()
{
//llSay( 0, "NSL ChatGPT Running");
llSetTimerEvent(0);
llResetTime();
read_notecards();
if (command_channel != 0) {
if (listen_hdl!=0) llListenRemove(listen_hdl);
listen_hdl = llListen(command_channel, "", NULL_KEY, "");
//llSay(0, "init_state: listen Channel = " + command_channel);
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
default
{
on_rez(integer _param)
{
command_channel = _param;
if (command_channel != 0) {
if (listen_hdl!=0) llListenRemove(listen_hdl);
listen_hdl = llListen(command_channel, "", NULL_KEY, "");
//llSay(0, "on_rez: listen Channel = " + command_channel);
}
}
state_entry()
{
init_state();
}
touch_start(integer _num_detected)
{
user_key = llDetectedKey(0);
user_name = llDetectedName(0);
npc_key = NULL_KEY;
start_conversation(user_name);
}
listen(integer _ch, string _name, key _id, string _message)
{
//llSay(0, "Receive Data from " + _ch + ": " + _id + ": " + _message);
// from Controller
// /### start user_key npc_key user_first_name user_last_name
if (_ch != 0 && _ch == command_channel) {
list _items = llParseString2List(_message, [" "], []);
string _cmd = llList2String(_items, 0);
if (llToLower(_cmd) == "start") {
integer _len = llGetListLength(_items);
if (_len > 3) {
user_key = llList2String(_items, 1);
npc_key = llList2String(_items, 2);
user_name = llList2String(_items, 3);
if (_len > 4) user_name += " " + llList2String(_items, 4);
start_conversation(user_name);
}
}
else if (llToLower(_cmd) == "stop") {
stop_conversation();
llDie();
}
}
// from User
else if (_id == user_key) {
//llSay(0, _message);
request_gpt_api(_message);
//
llSetTimerEvent(gap_time);
llResetTime();
time_count = 0;
}
else {
llSay(0, "NOING");
}
}
changed(integer _change)
{
if (_change & CHANGED_INVENTORY) {
//llSay(0, "Reread NoteCards");
read_notecards();
}
}
// ノートカードが一行読まれる度に発生するイベント
dataserver(key _requested_key, string _data)
{
// GPT Charactor
if (_requested_key == chara_notecard_key) {
if (_data != EOF){
chara_notecard += _data + "\n";
chara_notecard_line++;
chara_notecard_key = llGetNotecardLine(chara_notecard_name, chara_notecard_line);
}
else {
api_chara = chara_notecard;
}
}
// GPT API キー
else if (_requested_key == gptkey_notecard_key) {
if (_data != EOF){
gptkey_notecard += _data;
gptkey_notecard_line++;
gptkey_notecard_key = llGetNotecardLine(gptkey_notecard_name, gptkey_notecard_line);
}
else {
api_key = gptkey_notecard;
}
}
// GPT API Model
else if (_requested_key == model_notecard_key ) {
if (_data != EOF){
model_notecard += _data;
model_notecard_line++;
model_notecard_key = llGetNotecardLine(model_notecard_name, model_notecard_line);
}
else {
api_model = model_notecard;
}
}
}
http_response(key _request_id, integer _status, list _metadata, string _body)
{
llSetTimerEvent(0);
time_count = 0;
//
if (_status == 200) {
string _content = llJsonGetValue(_body, ["choices", 0, "message", "content"]);
//llSay(0, "BODY SIZE = " + llStringLength(_body));
//llSay(0, "CONTENT SIZE = " + llStringLength(_content));
//llSay(0, "Data = " + _body);
if (npc_key == NULL_KEY) {
for (integer p=0; p<llStringLength(_content); p+=say_bufsize) {
llRegionSayTo(user_key, 0, llGetSubString(_content, p, p+say_bufsize-1));
}
}
else {
for (integer p=0; p<llStringLength(_content); p+=say_bufsize) {
osNpcSayTo(npc_key, user_key, 0, llGetSubString(_content, p, p+say_bufsize-1));
}
}
}
// エラー応答
else {
if (npc_key == NULL_KEY) {
llRegionSayTo(user_key, 0, "リクエスト失敗: " + (string)_status + ", 応答内容: " + _body);
}
else {
osNpcSayTo(npc_key, user_key, 0, "リクエスト失敗: " + (string)_status + ", 応答内容: " + _body);
}
}
}
timer()
{
if (time_count==0) short_conversation("少々おまちください.");
else if (time_count==2) short_conversation("もうしばらくおまちください.");
else if (time_count==5) short_conversation("時間が掛かっています.");
time_count++;
}
}
NPC and NSL_ChatGPT Rezzer[edit]
// NPC and NSL_ChatGPT Rezzer v1.1.2
// support NSL_ChatCPT is v1.3.1
//
integer DEFAULT_CHANNEL = 683;
integer listen_hdl = 0;
//string anim_name = "irassyaimase";
string fname = "プロ生";
string lname = "ちゃん";
string appear_name = "ProNama_Red_Appearance";
// NPC List
integer list_stride = 3;
list npc_list = []; // [user_key, npc_key, channel] の繰り返し
// 指定したユーザがリストにあるかどうかをチェックする.
// ユーザが存在する場合は,npc_list中の位置を返す.
// ユーザが存在しない場合は -1 を返す
integer check_user_list(key _user_key)
{
integer _indx = 0;
integer _len = llGetListLength(npc_list);
for(_indx=0; _indx<_len; _indx+=list_stride) {
if (_user_key == (key)npc_list[_indx]) {
return _indx;
}
}
return -1;
}
// 指定したNPCがリストにあるかどうかをチェックする.
// NPCが存在する場合は,npc_list中の位置を返す.
// NPCが存在しない場合は -1 を返す
integer check_npc_list(key _npc_key)
{
integer _indx = 0;
integer _len = llGetListLength(npc_list);
for(_indx=0; _indx<_len; _indx+=list_stride) {
if (_npc_key == (key)npc_list[_indx + 1]) {
return _indx;
}
}
return -1;
}
// 指定したチャンネル番号がリストにあるかどうかをチェックする.
// チャンネル番号が存在する場合は,npc_list中の位置を返す.
// チャンネル番号が存在しない場合は -1 を返す
integer check_channel_list(integer _channel)
{
integer _indx = 0;
integer _len = llGetListLength(npc_list);
for(_indx=0; _indx<_len; _indx+=list_stride) {
if (_channel == (integer)npc_list[_indx + 2]) {
return _indx;
}
}
return -1;
}
integer get_valid_channel()
{
integer _channel = DEFAULT_CHANNEL + 1;
integer _indx = check_channel_list(_channel);
while (_indx != -1) {
_channel++;
_indx = check_channel_list(_channel);
}
return _channel;
}
// NPC の作成と NSL ChatGPT の Rez
key create_npc(key _user_key, vector _user_pos)
{
vector _npc_pos = llGetPos();
key _npc_key = osNpcCreate(fname, lname, _npc_pos, appear_name, OS_NPC_SENSE_AS_AGENT);
vector _move_to = _user_pos - llVecNorm(_user_pos - _npc_pos)*1.5; // 1.5m 離れた所
osNpcMoveTo(_npc_key, _move_to);
integer _channel = get_valid_channel();
llRezObject("NSL_ChatGPT", osNpcGetPos(_npc_key), <0.0, 0.0, 0.0>, <0.0, 0.0, 0.0, 1.0>, _channel);
npc_list = npc_list + [_user_key, _npc_key, _channel];
//llOwnerSay("NPC Key = " + _npc_key + ", Channel = " + _channel);
return _npc_key;
}
delete_all_npc()
{
integer _len = llGetListLength(npc_list);
integer _indx = 0;
for (_indx=0; _indx<_len; _indx += list_stride) {
key _npc_key = (key)npc_list[_indx + 1];
osNpcRemove(_npc_key);
}
npc_list = [];
}
init_script()
{
if (listen_hdl!=0) llListenRemove(listen_hdl);
listen_hdl = llListen(DEFAULT_CHANNEL, "", NULL_KEY, "");
delete_all_npc();
}
////////////////////////////////////////////////////////////////////////////////////////////
default
{
state_entry()
{
//llSay(0, "Script running");
init_script();
}
touch_start(integer _number)
{
key _user_key = llDetectedKey(0);
string _user_name = llDetectedName(0);
vector _user_pos = llDetectedPos(0);
integer _indx = check_user_list(_user_key);
// NPC と ChatGPT を起動
if (_indx==-1) {
key _npc_key = create_npc(_user_key, _user_pos);
llSleep(1.0);
integer _num = check_npc_list(_npc_key);
if (_num>=0) {
integer _channel = (integer)npc_list[_num + 2];
string _npc_name = fname + lname;
string _command = "start " + _user_key + " " + _npc_key + " " + _user_name;
llRegionSay(_channel, _command);
//llSay(0, "Send Data to " + _channel + ": " + _command);
}
}
// 既にNPCを起動している場合は,ChatGPTとNPCを削除
else if (_indx>=0) {
key _npc_key = (key)npc_list[_indx + 1];
integer _channel = (integer)npc_list[_indx + 2];
string _command = "stop";
llRegionSay(_channel, _command);
//llSay(0, "Send Data to " + _channel + ": " + _command);
llSleep(1.0);
osNpcRemove(_npc_key);
npc_list = llListReplaceList(npc_list, [], _indx, _indx + list_stride - 1);
}
}
listen(integer _ch, string _name, key _id, string _msg)
{
//llSay(0, "Recived Message: " + _msg);
list _items = llParseString2List(_msg, ["=", ",", " ", "\n"], []);
string _cmd = llList2String(_items, 0);
string _opr = llList2String(_items, 1);
if (_cmd=="" || _cmd==" ");
else if (llToLower(_cmd)=="delete" || llToLower(_cmd)=="del") {
if (_id == llGetOwner()) {
if (llToLower(_opr) == "all") {
delete_all_npc();
}
else {
key _npc_key = (key)_opr;
osNpcRemove(_npc_key);
integer _indx = check_npc_list(_npc_key);
if (_indx>=0) npc_list = llListReplaceList(npc_list, [], _indx, _indx + list_stride - 1);
}
}
}
}
//
on_rez(integer _start_param)
{
init_script();
llResetScript();
}
changed(integer _change)
{
//地域が再起動された場合
if (_change & CHANGED_REGION_START) {
init_script();
llResetScript();
}
else if (_change & CHANGED_INVENTORY) {
init_script();
llResetScript();
}
}
}