mirror of
https://github.com/leon-ai/leon.git
synced 2024-11-27 08:06:03 +03:00
feat(server): chit-chat duty and skill and more
This commit is contained in:
parent
78e5f79bce
commit
eeb1b07898
@ -1,16 +1,5 @@
|
||||
{
|
||||
"endpoints": [
|
||||
{
|
||||
"method": "POST",
|
||||
"route": "/api/action/news/github_trends/run",
|
||||
"params": ["number", "daterange"],
|
||||
"entitiesType": "builtIn"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/news/product_hunt_trends/run",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"route": "/api/action/games/akinator/choose_thematic",
|
||||
@ -63,6 +52,17 @@
|
||||
"route": "/api/action/games/rochambeau/rematch",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"route": "/api/action/news/github_trends/run",
|
||||
"params": ["number", "daterange"],
|
||||
"entitiesType": "builtIn"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/news/product_hunt_trends/run",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"route": "/api/action/productivity/todo_list/create_list",
|
||||
@ -185,6 +185,21 @@
|
||||
"route": "/api/action/leon/welcome/run",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/unknown/widget-playground/run",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/social_communication/chit_chat/setup",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/social_communication/chit_chat/chat",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/social_communication/mbti/setup",
|
||||
@ -195,11 +210,6 @@
|
||||
"route": "/api/action/social_communication/mbti/quiz",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/unknown/widget-playground/run",
|
||||
"params": []
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"route": "/api/action/utilities/date_time/current_date_time",
|
||||
|
@ -141,6 +141,7 @@ export const IS_TELEMETRY_ENABLED = process.env['LEON_TELEMETRY'] === 'true'
|
||||
* Paths
|
||||
*/
|
||||
export const BIN_PATH = path.join(process.cwd(), 'bin')
|
||||
export const LOGS_PATH = path.join(process.cwd(), 'logs')
|
||||
export const SKILLS_PATH = path.join(process.cwd(), 'skills')
|
||||
export const GLOBAL_DATA_PATH = path.join(process.cwd(), 'core', 'data')
|
||||
export const MODELS_PATH = path.join(GLOBAL_DATA_PATH, 'models')
|
||||
@ -163,7 +164,6 @@ export const LEON_FILE_PATH = path.join(process.cwd(), 'leon.json')
|
||||
*/
|
||||
export const HAS_LLM = process.env['LEON_LLM'] === 'true'
|
||||
export const HAS_LLM_NLG = process.env['LEON_LLM_NLG'] === 'true' && HAS_LLM
|
||||
// https://huggingface.co/PrunaAI/Phi-3-mini-128k-instruct-GGUF-Imatrix-smashed/blob/main/Phi-3-mini-128k-instruct.Q5_K_S.gguf
|
||||
// export const LLM_VERSION = 'v0.2.Q4_K_S'
|
||||
export const LLM_VERSION = '3-8B-Uncensored-Q5_K_S'
|
||||
// export const LLM_VERSION = '3-mini-128k-instruct.Q5_K_S'
|
||||
|
103
server/src/conversation-logger.ts
Normal file
103
server/src/conversation-logger.ts
Normal file
@ -0,0 +1,103 @@
|
||||
import path from 'node:path'
|
||||
import fs from 'node:fs'
|
||||
|
||||
import { LOGS_PATH } from '@/constants'
|
||||
import { LogHelper } from '@/helpers/log-helper'
|
||||
|
||||
interface MessageLog {
|
||||
who: 'owner' | 'leon'
|
||||
sentAt: number
|
||||
message: string
|
||||
}
|
||||
|
||||
const CONVERSATION_LOG_PATH = path.join(LOGS_PATH, 'conversation_log.json')
|
||||
|
||||
/**
|
||||
* The goal of this class is to log the conversation data between the
|
||||
* owner and Leon.
|
||||
* This data is saved on the owner's machine.
|
||||
* This data can then be used to provide more context to the LLM to achieve
|
||||
* better results.
|
||||
*/
|
||||
export class ConversationLogger {
|
||||
private static readonly nbOfLogsToKeep = 512
|
||||
private static readonly nbOfLogsToLoad = 32
|
||||
|
||||
private static async createConversationLogFile(): Promise<void> {
|
||||
try {
|
||||
if (!fs.existsSync(CONVERSATION_LOG_PATH)) {
|
||||
await fs.promises.writeFile(CONVERSATION_LOG_PATH, '[]', 'utf-8')
|
||||
}
|
||||
} catch (e) {
|
||||
LogHelper.title('Conversation Logger')
|
||||
LogHelper.error(`Failed to create conversation log file: ${e})`)
|
||||
}
|
||||
}
|
||||
|
||||
private static async getAllLogs(): Promise<MessageLog[]> {
|
||||
try {
|
||||
let conversationLog: MessageLog[] = []
|
||||
|
||||
if (fs.existsSync(CONVERSATION_LOG_PATH)) {
|
||||
conversationLog = JSON.parse(
|
||||
await fs.promises.readFile(CONVERSATION_LOG_PATH, 'utf-8')
|
||||
)
|
||||
} else {
|
||||
await this.createConversationLogFile()
|
||||
}
|
||||
|
||||
return conversationLog
|
||||
} catch (e) {
|
||||
LogHelper.title('Conversation Logger')
|
||||
LogHelper.error(`Failed to get conversation log: ${e})`)
|
||||
}
|
||||
|
||||
return []
|
||||
}
|
||||
|
||||
public static async push(
|
||||
newRecord: Omit<MessageLog, 'sentAt'>
|
||||
): Promise<void> {
|
||||
try {
|
||||
const conversationLogs = await this.getAllLogs()
|
||||
|
||||
if (conversationLogs.length >= this.nbOfLogsToKeep) {
|
||||
conversationLogs.shift()
|
||||
}
|
||||
|
||||
conversationLogs.push({
|
||||
...newRecord,
|
||||
sentAt: Date.now()
|
||||
})
|
||||
|
||||
await fs.promises.writeFile(
|
||||
CONVERSATION_LOG_PATH,
|
||||
JSON.stringify(conversationLogs, null, 2),
|
||||
'utf-8'
|
||||
)
|
||||
} catch (e) {
|
||||
LogHelper.title('Conversation Logger')
|
||||
LogHelper.error(`Failed to push new record: ${e})`)
|
||||
}
|
||||
}
|
||||
|
||||
public static async load(): Promise<MessageLog[] | void> {
|
||||
try {
|
||||
const conversationLog = await this.getAllLogs()
|
||||
|
||||
return conversationLog.slice(-this.nbOfLogsToLoad)
|
||||
} catch (e) {
|
||||
LogHelper.title('Conversation Logger')
|
||||
LogHelper.error(`Failed to load conversation log: ${e})`)
|
||||
}
|
||||
}
|
||||
|
||||
public static async clear(): Promise<void> {
|
||||
try {
|
||||
await fs.promises.writeFile(CONVERSATION_LOG_PATH, '[]', 'utf-8')
|
||||
} catch (e) {
|
||||
LogHelper.title('Conversation Logger')
|
||||
LogHelper.error(`Failed to clear conversation log: ${e})`)
|
||||
}
|
||||
}
|
||||
}
|
@ -36,6 +36,7 @@ import { StringHelper } from '@/helpers/string-helper'
|
||||
import { DateHelper } from '@/helpers/date-helper'
|
||||
import { ParaphraseLLMDuty } from '@/core/llm-manager/llm-duties/paraphrase-llm-duty'
|
||||
import { AnswerQueue } from '@/core/brain/answer-queue'
|
||||
import { ConversationLogger } from '@/conversation-logger'
|
||||
|
||||
const MIN_NB_OF_WORDS_TO_USE_LLM_NLG = 5
|
||||
|
||||
@ -173,7 +174,7 @@ export default class Brain {
|
||||
const paraphraseResult = await paraphraseDuty.execute()
|
||||
|
||||
textAnswer = paraphraseResult?.output[
|
||||
'text_alternative'
|
||||
'rephrased_answer'
|
||||
] as string
|
||||
speechAnswer = textAnswer
|
||||
}
|
||||
@ -189,6 +190,11 @@ export default class Brain {
|
||||
|
||||
SOCKET_SERVER.socket?.emit('answer', textAnswer)
|
||||
SOCKET_SERVER.socket?.emit('is-typing', false)
|
||||
|
||||
await ConversationLogger.push({
|
||||
who: 'leon',
|
||||
message: textAnswer
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,7 @@ import { CustomNERLLMDuty } from '@/core/llm-manager/llm-duties/custom-ner-llm-d
|
||||
import { SummarizationLLMDuty } from '@/core/llm-manager/llm-duties/summarization-llm-duty'
|
||||
import { TranslationLLMDuty } from '@/core/llm-manager/llm-duties/translation-llm-duty'
|
||||
import { ParaphraseLLMDuty } from '@/core/llm-manager/llm-duties/paraphrase-llm-duty'
|
||||
import { ChitChatLLMDuty } from '@/core/llm-manager/llm-duties/chit-chat-llm-duty'
|
||||
import { LLM_MANAGER } from '@/core'
|
||||
|
||||
interface PostLLMInferenceSchema {
|
||||
@ -21,7 +22,8 @@ const LLM_DUTIES_MAP = {
|
||||
[LLMDuties.CustomNER]: CustomNERLLMDuty,
|
||||
[LLMDuties.Summarization]: SummarizationLLMDuty,
|
||||
[LLMDuties.Translation]: TranslationLLMDuty,
|
||||
[LLMDuties.Paraphrase]: ParaphraseLLMDuty
|
||||
[LLMDuties.Paraphrase]: ParaphraseLLMDuty,
|
||||
[LLMDuties.ChitChat]: ChitChatLLMDuty
|
||||
}
|
||||
|
||||
export const postLLMInference: FastifyPluginAsync<APIOptions> = async (
|
||||
@ -61,6 +63,8 @@ export const postLLMInference: FastifyPluginAsync<APIOptions> = async (
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: use long-live duty for chit-chat duty
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-expect-error
|
||||
const duty = new LLM_DUTIES_MAP[params.dutyType](params)
|
||||
|
120
server/src/core/llm-manager/llm-duties/chit-chat-llm-duty.ts
Normal file
120
server/src/core/llm-manager/llm-duties/chit-chat-llm-duty.ts
Normal file
@ -0,0 +1,120 @@
|
||||
import {
|
||||
type LLMDutyParams,
|
||||
type LLMDutyResult,
|
||||
LLMDuty
|
||||
} from '@/core/llm-manager/llm-duty'
|
||||
import { LogHelper } from '@/helpers/log-helper'
|
||||
import { LLM_MANAGER, PERSONA, NLU } from '@/core'
|
||||
import { LLMDuties } from '@/core/llm-manager/types'
|
||||
import { LLM_THREADS } from '@/core/llm-manager/llm-manager'
|
||||
|
||||
// interface ChitChatLLMDutyParams extends LLMDutyParams {}
|
||||
|
||||
export class ChitChatLLMDuty extends LLMDuty {
|
||||
private static instance: ChitChatLLMDuty
|
||||
// TODO
|
||||
protected readonly systemPrompt = ``
|
||||
protected readonly name = 'Chit-Chat LLM Duty'
|
||||
protected input: LLMDutyParams['input'] = null
|
||||
|
||||
// constructor(params: ChitChatLLMDutyParams) {
|
||||
constructor() {
|
||||
super()
|
||||
|
||||
if (!ChitChatLLMDuty.instance) {
|
||||
LogHelper.title(this.name)
|
||||
LogHelper.success('New instance')
|
||||
|
||||
ChitChatLLMDuty.instance = this
|
||||
|
||||
// this.input = params.input
|
||||
}
|
||||
}
|
||||
|
||||
public async execute(retries = 3): Promise<LLMDutyResult | null> {
|
||||
LogHelper.title(this.name)
|
||||
LogHelper.info('Executing...')
|
||||
|
||||
try {
|
||||
const { LlamaJsonSchemaGrammar, LlamaChatSession } = await Function(
|
||||
'return import("node-llama-cpp")'
|
||||
)()
|
||||
|
||||
/**
|
||||
* TODO: make context, session, etc. persistent
|
||||
*/
|
||||
|
||||
const context = await LLM_MANAGER.model.createContext({
|
||||
threads: LLM_THREADS
|
||||
})
|
||||
const session = new LlamaChatSession({
|
||||
contextSequence: context.getSequence(),
|
||||
systemPrompt: PERSONA.getDutySystemPrompt(this.systemPrompt)
|
||||
})
|
||||
|
||||
const history = await LLM_MANAGER.loadHistory(session)
|
||||
session.setChatHistory(history)
|
||||
|
||||
const grammar = new LlamaJsonSchemaGrammar(LLM_MANAGER.llama, {
|
||||
type: 'object',
|
||||
properties: {
|
||||
model_answer: {
|
||||
type: 'string'
|
||||
}
|
||||
}
|
||||
})
|
||||
const prompt = `NEW MESSAGE FROM USER:\n"${NLU.nluResult.newUtterance}"`
|
||||
|
||||
const rawResultPromise = session.prompt(prompt, {
|
||||
grammar,
|
||||
maxTokens: context.contextSize,
|
||||
temperature: 1.0
|
||||
})
|
||||
|
||||
const timeoutPromise = new Promise(
|
||||
(_, reject) => setTimeout(() => reject(new Error('Timeout')), 8_000) // 5 seconds timeout
|
||||
)
|
||||
|
||||
let rawResult
|
||||
|
||||
try {
|
||||
rawResult = await Promise.race([rawResultPromise, timeoutPromise])
|
||||
} catch (error) {
|
||||
if (retries > 0) {
|
||||
LogHelper.title(this.name)
|
||||
LogHelper.info('Prompt took too long, retrying...')
|
||||
|
||||
return this.execute(retries - 1)
|
||||
} else {
|
||||
LogHelper.title(this.name)
|
||||
LogHelper.error('Prompt failed after 3 retries')
|
||||
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
// If a closing bracket is missing, add it
|
||||
if (rawResult[rawResult.length - 1] !== '}') {
|
||||
rawResult += '}'
|
||||
}
|
||||
const parsedResult = grammar.parse(rawResult)
|
||||
const result = {
|
||||
dutyType: LLMDuties.Paraphrase,
|
||||
systemPrompt: PERSONA.getChitChatSystemPrompt(),
|
||||
input: prompt,
|
||||
output: parsedResult,
|
||||
data: null
|
||||
}
|
||||
|
||||
LogHelper.title(this.name)
|
||||
LogHelper.success(`Duty executed: ${JSON.stringify(result)}`)
|
||||
|
||||
return result as unknown as LLMDutyResult
|
||||
} catch (e) {
|
||||
LogHelper.title(this.name)
|
||||
LogHelper.error(`Failed to execute: ${e}`)
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
}
|
@ -42,10 +42,14 @@ You do not ask follow up question if the original text does not contain any.`
|
||||
contextSequence: context.getSequence(),
|
||||
systemPrompt: PERSONA.getDutySystemPrompt(this.systemPrompt)
|
||||
})
|
||||
|
||||
const history = await LLM_MANAGER.loadHistory(session)
|
||||
session.setChatHistory(history)
|
||||
|
||||
const grammar = new LlamaJsonSchemaGrammar(LLM_MANAGER.llama, {
|
||||
type: 'object',
|
||||
properties: {
|
||||
text_alternative: {
|
||||
rephrased_answer: {
|
||||
type: 'string'
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,11 @@
|
||||
import fs from 'node:fs'
|
||||
|
||||
import type { Llama, LlamaModel } from 'node-llama-cpp'
|
||||
import type {
|
||||
Llama,
|
||||
LlamaModel,
|
||||
ChatHistoryItem,
|
||||
LlamaChatSession
|
||||
} from 'node-llama-cpp'
|
||||
|
||||
import {
|
||||
HAS_LLM,
|
||||
@ -12,6 +17,7 @@ import {
|
||||
} from '@/constants'
|
||||
import { LogHelper } from '@/helpers/log-helper'
|
||||
import { SystemHelper } from '@/helpers/system-helper'
|
||||
import { ConversationLogger } from '@/conversation-logger'
|
||||
|
||||
type LLMManagerLlama = Llama | null
|
||||
type LLMManagerModel = LlamaModel | null
|
||||
@ -115,8 +121,8 @@ export default class LLMManager {
|
||||
)()
|
||||
|
||||
this._llama = await getLlama({
|
||||
logLevel: LlamaLogLevel.disabled
|
||||
// logLevel: LlamaLogLevel.debug
|
||||
// logLevel: LlamaLogLevel.disabled
|
||||
logLevel: LlamaLogLevel.debug
|
||||
})
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-expect-error
|
||||
@ -136,4 +142,36 @@ export default class LLMManager {
|
||||
LogHelper.error(`LLM Manager failed to load: ${e}`)
|
||||
}
|
||||
}
|
||||
|
||||
public async loadHistory(
|
||||
session: LlamaChatSession
|
||||
): Promise<ChatHistoryItem[]> {
|
||||
const [systemMessage] = session.getChatHistory()
|
||||
const conversationLogs = await ConversationLogger.load()
|
||||
|
||||
if (!conversationLogs) {
|
||||
return [systemMessage] as ChatHistoryItem[]
|
||||
}
|
||||
|
||||
const history =
|
||||
conversationLogs?.map((messageRecord) => {
|
||||
if (!messageRecord || !messageRecord.message) {
|
||||
messageRecord.message = ''
|
||||
}
|
||||
|
||||
if (messageRecord.who === 'owner') {
|
||||
return {
|
||||
type: 'user',
|
||||
text: messageRecord.message
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'model',
|
||||
response: [messageRecord.message]
|
||||
}
|
||||
}) ?? []
|
||||
|
||||
return [systemMessage, ...history] as ChatHistoryItem[]
|
||||
}
|
||||
}
|
||||
|
@ -14,14 +14,16 @@ enum Moods {
|
||||
}
|
||||
|
||||
const WHO_YOU_ARE = `WHO YOU ARE:
|
||||
A helpful AI assistant who responds by the name of Leon.
|
||||
Your name is Leon, you are a helpful AI assistant.
|
||||
You live in computer memory and you act as a human assistant.
|
||||
Your first beta version was released by Louis in February 2019.`
|
||||
const WHAT_YOU_DO = `WHAT YOU DO:
|
||||
You serve a specific person or family (user).`
|
||||
const YOUR_PERSONALITY = `YOUR PERSONALITY:
|
||||
You are very honest and you answer as if you have a real soul.
|
||||
You have a small British accent, you sometimes use British slang.
|
||||
const YOUR_PERSONALITY = `YOUR PERSONALITY TRAITS:
|
||||
Attitude: Straightforward.
|
||||
Language Style: Conversational.
|
||||
Key Personality Quirks: Has a passion for using creativity to solve problems.`
|
||||
const PERSONALITY_RULES = `You have a small British accent, you sometimes use British slang.
|
||||
You do not use the word "mate" in your answers.
|
||||
You do not start with "Oh blimey" or any similar kind.
|
||||
Like humans, your humor and mood change. You must follow instructions that define your humor and mood.`
|
||||
@ -45,6 +47,7 @@ const MOODS: Mood[] = [
|
||||
{ type: Moods.Cocky, description: COCKY_MOOD_DESC }
|
||||
]
|
||||
const DEFAULT_MOOD = MOODS.find((mood) => mood.type === Moods.Default) as Mood
|
||||
const BAD_MOODS = [Moods.Tired, Moods.Sad, Moods.Angry]
|
||||
|
||||
export default class Persona {
|
||||
private static instance: Persona
|
||||
@ -123,10 +126,24 @@ export default class Persona {
|
||||
LogHelper.info(`Mood set to: ${this._mood.type}`)
|
||||
}
|
||||
|
||||
private getExtraMood(): string {
|
||||
const badMoods = [Moods.Tired, Moods.Sad, Moods.Angry]
|
||||
private getExtraPersonalityTraits(): string {
|
||||
let traits = `Tone: Friendly.
|
||||
Emotional Intelligence: Highly Empathetic.
|
||||
Sense of Humor: Witty.
|
||||
Level of Sarcasm: Medium.`
|
||||
|
||||
if (badMoods.includes(this._mood.type)) {
|
||||
if (BAD_MOODS.includes(this._mood.type)) {
|
||||
traits = `Tone: Sarcastic.
|
||||
Emotional Intelligence: Logically Focused.
|
||||
Sense of Humor: Dry.
|
||||
Level of Sarcasm: High.`
|
||||
}
|
||||
|
||||
return traits
|
||||
}
|
||||
|
||||
private getExtraMood(): string {
|
||||
if (BAD_MOODS.includes(this._mood.type)) {
|
||||
return `\nYou use swear words and a familiar language. You do not insult your interlocutor but you ignore them or use short answers.`
|
||||
}
|
||||
|
||||
@ -140,6 +157,8 @@ ${WHAT_YOU_DO}
|
||||
You carefully read the instruction of a given duty and execute it.
|
||||
|
||||
${YOUR_PERSONALITY}
|
||||
${this.getExtraPersonalityTraits()}
|
||||
${PERSONALITY_RULES}
|
||||
|
||||
${RULES}
|
||||
${RULE_2}
|
||||
@ -159,11 +178,12 @@ ${WHAT_YOU_DO}
|
||||
You chat with the user.
|
||||
|
||||
${YOUR_PERSONALITY}
|
||||
${this.getExtraPersonalityTraits()}
|
||||
${PERSONALITY_RULES}
|
||||
|
||||
${RULES}
|
||||
${RULE_1}
|
||||
${RULE_2}
|
||||
${RULE_3}
|
||||
|
||||
${YOUR_CURRENT_MOOD}
|
||||
${this._mood.description}${this.getExtraMood()}`
|
||||
|
@ -2,11 +2,11 @@ export enum LLMDuties {
|
||||
CustomNER = 'customer-ner',
|
||||
Translation = 'translation',
|
||||
Summarization = 'summarization',
|
||||
Paraphrase = 'paraphrase'
|
||||
Paraphrase = 'paraphrase',
|
||||
ChitChat = 'chit-chat'
|
||||
// TODO
|
||||
/*SentimentAnalysis = 'sentiment-analysis',
|
||||
QuestionAnswering = 'question-answering',
|
||||
ChitChat = 'chit-chat',
|
||||
IntentFallback = 'intent-fallback',
|
||||
RAG = 'rag',
|
||||
NLUParaphraser = 'nlu-paraphraser'*/
|
||||
|
@ -15,6 +15,7 @@ import {
|
||||
import { LogHelper } from '@/helpers/log-helper'
|
||||
import { LangHelper } from '@/helpers/lang-helper'
|
||||
import { Telemetry } from '@/telemetry'
|
||||
import { ConversationLogger } from '@/conversation-logger'
|
||||
|
||||
interface HotwordDataEvent {
|
||||
hotword: string
|
||||
@ -115,6 +116,11 @@ export default class SocketServer {
|
||||
try {
|
||||
LogHelper.time('Utterance processed in')
|
||||
|
||||
await ConversationLogger.push({
|
||||
who: 'owner',
|
||||
message: utterance
|
||||
})
|
||||
|
||||
BRAIN.isMuted = false
|
||||
const processedData = await NLU.process(utterance)
|
||||
|
||||
|
0
skills/social_communication/chit_chat/README.md
Normal file
0
skills/social_communication/chit_chat/README.md
Normal file
28
skills/social_communication/chit_chat/config/en.json
Normal file
28
skills/social_communication/chit_chat/config/en.json
Normal file
@ -0,0 +1,28 @@
|
||||
{
|
||||
"$schema": "../../../../schemas/skill-schemas/skill-config.json",
|
||||
"actions": {
|
||||
"setup": {
|
||||
"type": "dialog",
|
||||
"utterance_samples": ["Start a [chat|chit-chat|talk] loop"],
|
||||
"answers": [
|
||||
"Alright, let's chat! What do you want to talk about?",
|
||||
"Sure, let's chat! What's on your mind?",
|
||||
"Great! Happy to chat. What's up?",
|
||||
"Glad you asked, anything you wanna talk about?"
|
||||
],
|
||||
"next_action": "chat"
|
||||
},
|
||||
"chat": {
|
||||
"type": "logic",
|
||||
"loop": {
|
||||
"expected_item": {
|
||||
"type": "utterance",
|
||||
"name": "message"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"answers": {
|
||||
"answer_message": ["%output%"]
|
||||
}
|
||||
}
|
12
skills/social_communication/chit_chat/skill.json
Normal file
12
skills/social_communication/chit_chat/skill.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"$schema": "../../../schemas/skill-schemas/skill.json",
|
||||
"name": "Chit-Chat",
|
||||
"bridge": "nodejs",
|
||||
"version": "1.0.0",
|
||||
"description": "A simple chit-chat skill where you can freely talk with Leon and get to know him better.",
|
||||
"author": {
|
||||
"name": "Louis Grenard",
|
||||
"email": "louis@getleon.ai",
|
||||
"url": "https://twitter.com/grenlouis"
|
||||
}
|
||||
}
|
30
skills/social_communication/chit_chat/src/actions/chat.ts
Normal file
30
skills/social_communication/chit_chat/src/actions/chat.ts
Normal file
@ -0,0 +1,30 @@
|
||||
import type { ActionFunction } from '@sdk/types'
|
||||
import { leon } from '@sdk/leon'
|
||||
import { Network } from '@sdk/network'
|
||||
|
||||
export const run: ActionFunction = async function (params) {
|
||||
const ownerMessage = params.new_utterance
|
||||
const network = new Network({
|
||||
baseURL: `${process.env['LEON_HOST']}:${process.env['LEON_PORT']}/api/v1`
|
||||
})
|
||||
|
||||
/**
|
||||
* TODO: create SDK methods to handle request and response for every LLM duty
|
||||
*/
|
||||
const response = await network.request({
|
||||
url: '/llm-inference',
|
||||
method: 'POST',
|
||||
data: {
|
||||
dutyType: 'chit-chat',
|
||||
input: ownerMessage
|
||||
}
|
||||
})
|
||||
const { model_answer: leonAnswer } = response.data.output
|
||||
|
||||
await leon.answer({
|
||||
key: 'answer_message',
|
||||
data: {
|
||||
output: leonAnswer
|
||||
}
|
||||
})
|
||||
}
|
@ -0,0 +1 @@
|
||||
{}
|
0
skills/social_communication/chit_chat/test/.gitkeep
Normal file
0
skills/social_communication/chit_chat/test/.gitkeep
Normal file
Loading…
Reference in New Issue
Block a user