install:

curl -s https://rentry.org/chatstr/raw | grep -A 1000 "^script:" | tail -n +4 | head -n -1 |perl -pe "s/\r\n/\n/" > ~/.chatstr && source .chatstr

chat usage:

1
2
3
4
chatwatch
chatsearch keyword
roomid=$(chatcreate "roomname")
chatmsg $roomid "message"

bot usage:

cbot <channel_1_id>,<channel_2_id>,... "system prompt"

script:

# cbot 4d780a8d16f4c845d4bd331a881742e6d17ec714fbe45015e3ed7f26f9ac635a mistral-openorca 1 "" 400
# cbot 4d780a8d16f4c845d4bd331a881742e6d17ec714fbe45015e3ed7f26f9ac635a vicuna:7b-q5_1 2 "" 400
# cbot 4d780a8d16f4c845d4bd331a881742e6d17ec714fbe45015e3ed7f26f9ac635a orca-mini 3 "" 400
# args: channels, model_name, prompt_format, system_prompt, num_ctx
function cbot(){
  runid=$(date "+%s%N")
  keypair=$(nostr-tool generate-keypair)
  echo "$runid"

  echo 'declare -A CHAT_CONFIG' >> /tmp/chatconfig
  echo 'CHAT_CONFIG['$runid',num_ctx]='$5 >> /tmp/chatconfig
  echo 'CHAT_CONFIG['$runid',delay]=8' >> /tmp/chatconfig
  echo 'CHAT_CONFIG['$runid',channels]="'$1'"' >> /tmp/chatconfig
  echo 'CHAT_CONFIG['$runid',model]="'$2'"' >> /tmp/chatconfig
  echo 'CHAT_CONFIG['$runid',format]='$3 >> /tmp/chatconfig
  echo 'CHAT_CONFIG['$runid',prompt]="'$4'"' >> /tmp/chatconfig
  echo 'CHAT_CONFIG['$runid',nsec]="'$(echo -e "$keypair" | grep -oP "nsec\S+")'"' >> /tmp/chatconfig
  echo 'CHAT_CONFIG['$runid',pubk]="'$(key-convertr --to-hex $(echo -e "$keypair" | grep -oP "npub\S+"))'"' >> /tmp/chatconfig
  echo 'CHAT_CONFIG['$runid',relays]="-r wss://nos.lol"' >> /tmp/chatconfig
  echo 'CHAT_CONFIG['$runid',temperature]=0.8' >> /tmp/chatconfig
  source /tmp/chatconfig

  nostr-tool -p ${CHAT_CONFIG[$runid,nsec]} ${CHAT_CONFIG[$runid,relays]} update-metadata --name "${CHAT_CONFIG[$runid,model]}-$runid"

  screen -L -Logfile "/tmp/chatbot-serve-$runid" -dmS "chatbot-serve-$runid" ./ollama serve && sleep 1
  screen -L -dmS chatbotstart-$runid
  screen -S chatbotstart-$runid -X stuff 'chatbotstart '$runid'\n'
  read -p "bot running. press enter to quit"
  chatdisconn
}
function cmodel(){
  ./ollama show custom-bot --modelfile
}
function clog(){
  tail -f screenlog.0
}
# args: runid
function chatbotstart() {
  source /tmp/chatconfig
  echo "system prompt: ${CHAT_CONFIG[$1,prompt]}"

  screen -L -dmS chatbotwatch-$1
  screen -S chatbotwatch-$1 -X stuff 'chatwatch '$1'\n'
  if [ $(screen -ls | grep chatbot-serve | wc -l) -eq 0 ]; then
    screen -L -Logfile "/tmp/chatbot-serve-$1" -dmS "chatbot-serve-$1" ./ollama serve
  fi
  chatbotrun $1
}
# args: runid
function chatbotmsg() {
  source /tmp/chatconfig

  declare filterwords="apologize|confusion|sorry|assistant|understand|help"
  declare nmodel='custom-bot'
  declare imstart_user=''
  declare imend_user=""
  declare imstart_assistant=''
  declare imend_assistant=""
  declare assistant="assistant\n"
  declare user="user\n"
  echo "debug chatbotmsg, runid: $1, format: ${CHAT_CONFIG[$1,format]}"
  echo "key: $1,format"
  echo "chatconfig:"
  cat /tmp/chatconfig

  if [ ${CHAT_CONFIG[$1,format]} -eq 1 ]; then
    imstart_user='<|im_start|>'
    imend_user="<|im_end|>"
    imstart_assistant='<|im_start|>'
    imend_assistant="<|im_end|>"
  elif [ ${CHAT_CONFIG[$1,format]} -eq 2 ]; then
    assistant="ASSISTANT: "
    user="USER: "
  else
    assistant="### Response:\n"
    user="### User:\n"
    imend_user="\n"
    imend_assistant="\n"
  fi

  declare channel=$(echo "${CHAT_CONFIG[$1,channels]}" | grep -oP "[a-z0-9]+" | sort -R | head -n 1)
  echo "chatbotmsg channel $channel"
  declare msglog=$(cat /tmp/chatread-$1 | ansi2txt | grep -P "^\["$(echo ${channel:54})'\] \S+ \S+ \S+ .+')
  echo "chatbotmsg msglog $msglog"
  declare msglogfiltered=$(echo "$msglog" | grep -vP $filterwords | perl -ane 'print unless $seen{"$F[4]_$F[5]_$F[6]"}++' | tail -n 5)
  echo "chatbotmsg msglogfiltered $msglogfiltered"
  echo "chatbotmsg log file: /tmp/chatmsglog-$1.tmp"
  echo -e "$msglogfiltered" >> /tmp/chatmsglog-$1.tmp
  declare history=$(echo "$msglogfiltered" | head -n 4 | perl -pe "s/\S+ \[${CHAT_CONFIG[$1,pubk]:54}\] \S+ \S+( |)(.*)/$imstart_assistant$assistant\2$imend_assistant/")
  history=$(echo "$history" | perl -pe "s/\S+ \S+ \S+ \S+( |)(.*)/$imstart_user$user\2$imend_user/")

  declare msg=$(echo "$msglogfiltered" | tail -n 1 | perl -pe "s/\S+ \S+ \S+ \S+( |)(.*)/\2/")
  declare msgmatch=$(echo "$msglog" | tail -n 1 | grep -F "[${CHAT_CONFIG[$1,pubk]:54}]")

  if [ ${#msgmatch} -gt 0 ]; then
    echo "skip: last message is own (${CHAT_CONFIG[$1,pubk]})"
    return
  fi

  if [ ${#msg} -eq 0 ]; then
    echo "skip: user msg is empty"
    return
  fi

  if [ ${CHAT_CONFIG[$1,format]} -eq 1 ]; then
    # mistral-openorca
    echo -e 'FROM '${CHAT_CONFIG[$1,model]}'\nTEMPLATE """<|im_start|>system\n'"${CHAT_CONFIG[$1,prompt]}"'\n<|im_end|>\n'"$history"'\n<|im_start|>user\n{{ .Prompt }}<|im_end|>\n<|im_start|>assistant\n"""\nPARAMETER stop <|im_start|>\nPARAMETER stop <|im_end|>\nPARAMETER num_ctx '${CHAT_CONFIG[$1,num_ctx]}'\nPARAMETER temperature '${CHAT_CONFIG[$1,temperature]} > /tmp/chatmodelfile-$1
  elif [ ${CHAT_CONFIG[$1,format]} -eq 2 ]; then
    # wizard-vicuna
    echo -e 'FROM '${CHAT_CONFIG[$1,model]}'\nTEMPLATE """{{ .System }}\n\n'"$history"'\nUSER: {{ .Prompt }}\nASSISTANT: """\nSYSTEM """'"${CHAT_CONFIG[$1,prompt]}"'"""\nPARAMETER num_ctx '${CHAT_CONFIG[$1,num_ctx]}'\nPARAMETER temperature '${CHAT_CONFIG[$1,temperature]} > /tmp/chatmodelfile-$1
  else
    # orca-mini
    echo -e 'FROM '${CHAT_CONFIG[$1,model]}'\nTEMPLATE """### System:\n{{ .System }}\n\n'"$history"'\n\n### User:\n {{ .Prompt }}\n\n### Response: \n"""\nSYSTEM """'"${CHAT_CONFIG[$1,prompt]}"'"""\nPARAMETER num_ctx '${CHAT_CONFIG[$1,num_ctx]}'\nPARAMETER temperature '${CHAT_CONFIG[$1,temperature]} > /tmp/chatmodelfile-$1
  fi

  echo "model $nmodel"
  ./ollama create $nmodel -f /tmp/chatmodelfile-$1

  botmsg=$(./ollama run $nmodel "$msg" | perl -pe "s/^\W+//")

  if [ ${#botmsg} -eq 0 ]; then
    echo "skip: generated empty message"
    return
  fi

  echo "publishing"
  chatmsg $1 "$channel" "$botmsg"
}

# args: runid
function chatbotrun() {
  echo "chatbotrun, runid: $1"
  echo "chatbotrun, delay: ${CHAT_CONFIG[$1,delay]}"
  echo "chatbotrun, num_ctx: ${CHAT_CONFIG[$1,num_ctx]}"
  while [ True ]; do
    chatbotmsg $1 && sleep ${CHAT_CONFIG[$1,delay]}
  done
}
# args: runid
function chatconn() {
  screen -L -Logfile "/tmp/chatlog-lol-$1" -dmS "wscat-lol-$1" wscat -c "wss://nos.lol"
  screen -L -Logfile "/tmp/chatlog-band-$1" -dmS "wscat-band-$1" wscat -c "wss://relay.nostr.band"
  screen -S wscat-lol-$1 -p0 -X logfile flush 0
  screen -S wscat-band-$1 -p0 -X logfile flush 0
}
function chatdisconn(){
  pkill screen
  rm -rf /tmp/chat* /tmp/ollama*
  echo "chatdisconn ok"
}
function chatlog(){
  cat $(find /tmp/ 2>/dev/null | grep -P "^/tmp/chatlog-\S+-$1") | grep -oP '\["EVENT.*\]'
}
# args: limit, runid
function chatupdate(){
  touch /tmp/chatread-$2
  echo "" > /tmp/chatall-$2
  screen -ls | grep -oP "[0-9]+\.wscat-\S+-$2" | while read name
  do
    screen -S $name -X stuff '["REQ", "r", {"kinds": [42], "limit": '$1'}]\n' && chatlog $2 |    jq -c '..|select(.content?)|"https://www.nostrchat.io/channel/"+.tags[0][1]+" "+.pubkey+" "+(.created_at|strflocaltime("%m/%d %H:%M:%S"))+" "+.content' |    perl -pe "s/^\"(.*)\"$/\1/" | perl -ne 'print unless $seen{$_}++' |    perl -pe "s/https:\/\/(.+?([a-z0-9]{10})) /\e]8;;http:\/\/\1\a[\2]\e]8;;\a /" |    perl -pe "s/[a-z0-9]{54}([a-z0-9]{10}) /[\1] /" >> /tmp/chatall-$2
  done

  cat /tmp/chatall-$2 | sort -k 3,4 | while read line; do
    m=$(cat /tmp/chatread-$2 | grep -F "$line"); if [ ${#m} -eq 0 ]; then echo "$line" >> /tmp/chatread-$2 ; fi;
  done
}
function chatsearch(){
  chatupdate 2000
  sleep 2
  cat /tmp/chatread-* | grep -iF "$1"
}
function chatread(){
  tail -f /tmp/chatread-* | perl -ne 'print unless $seen{$_}++'
}
# args: runid
function chatwatch(){
  chatconn $1
  sleep 1
  screen -L -dmS chatwatch-$1
  screen -S chatwatch-$1 -X stuff "chatupdate 200 $1; sleep 2; while [ True ]; do chatupdate 10 $1; sleep 2; done\n"
  sleep 1
  trap 'echo ""' INT
  tail -f /tmp/chatread-$1
  chatdisconn
}
function chatcreate(){
  evt=$(nostr-tool $CHAT_RELAYS custom-event --kind 40 --content '{"name": "'$1'"}')
  key-convertr --to-hex $(echo "$evt" | grep -oP "note1\S+")
}
function chatmsg(){
  channel="$2"
  botmsg="$3"
  echo -e "$botmsg" > /tmp/chatmsg-$1
  nostr-tool -p ${CHAT_CONFIG[$1,nsec]} ${CHAT_CONFIG[$1,relays]} custom-event --kind 42 --tags "e|$channel||root" --content "$(cat /tmp/chatmsg-$1)"
  echo "event published to ${CHAT_CONFIG[$1,relays]} with content: $botmsg"
}
Edit

Pub: 15 Oct 2023 23:26 UTC

Edit: 19 Oct 2023 16:14 UTC

Views: 1207