Loading files
7ef7a9307This file is pinned to the selected release. Download the original to open it in your design tool.
import Timer from 'timer'
import { randomBetween } from 'stackchan-util'
import loadPreferences from 'loadPreference'
import WebSocket from 'WebSocket'
import { ChatGPTDialogue } from 'dialogue-chatgpt'
const STT_HOST = 'stackchan-base.local'
const MODEL = 'gpt-4o-mini'
const CONTEXT = [
{
role: 'system',
content:
'You are "スタックちゃん(Stack-chan)", the palm sized super kawaii companion robot baby. You must response in a short sentense.',
},
{
role: 'assistant',
content: 'ぼく、スタックちゃん!ねえ、お話しようよ!',
},
]
export function onRobotCreated(robot) {
// Integrate ChatGPT
const aiPrefs = loadPreferences('ai')
trace(`ai.token: ${aiPrefs.token}\n`)
const dialogue = new ChatGPTDialogue({
apiKey: aiPrefs.token,
model: MODEL,
context: CONTEXT,
})
let chatting = false
async function chatAndSay(message) {
if (chatting) {
return
}
chatting = true
const result = await dialogue.post(message)
if (!result.success) {
trace(`failed: ${result.reason}`)
return
}
const messages = result.value.split(/[。!?]/).filter((m) => m.length > 0)
for (const message of messages) {
ws.send(
JSON.stringify({
role: 'assistant',
message,
}),
)
await robot.say(message)
}
chatting = false
}
// Connect to STT server
const ttsPrefs = loadPreferences('tts')
const ws = new WebSocket(`ws://${ttsPrefs.host ?? STT_HOST}:8080`)
ws.addEventListener('open', () => {
trace('connected\n')
})
ws.addEventListener('message', (payload) => {
if (payload.data != null && payload.data.length > 1) {
const { role, message } = JSON.parse(payload.data)
if (role === 'user') {
chatAndSay(message)
}
}
})
ws.addEventListener('close', () => {
trace('disconnected\n')
})
// Event handler
let isFollowing = false
robot.button.a.onChanged = async function handleButtonAChanged() {
if (this.read()) {
trace('pressed A\n')
trace('Look around\n')
isFollowing = !isFollowing
}
}
robot.button.b.onChanged = async function handleButtonBChanged() {
if (this.read()) {
trace('pressed B\n')
trace('Chat test\n')
await chatAndSay('おはようございます')
}
}
robot.button.c.onChanged = async function handleButtonCChanged() {
if (this.read()) {
trace('pressed C\n')
trace('TTS test\n')
if (chatting) {
return
}
chatting = true
await robot.say('こんにちは。ぼくスタックチャン!')
await robot.say('よろしくね。')
chatting = false
}
}
// Look around
const lookAround = () => {
if (!isFollowing) {
robot.lookAway()
return
}
const x = randomBetween(0.4, 1.0)
const y = randomBetween(-0.4, 0.4)
const z = randomBetween(-0.02, 0.2)
trace(`looking at: [${x}, ${y}, ${z}]\n`)
robot.lookAt([x, y, z])
}
Timer.repeat(lookAround, 5000)
}