80 lines
3.4 KiB
Lua
80 lines
3.4 KiB
Lua
|
|
-- Summarise the last N turns of LLM conversation in 1-2 sentences.
|
|||
|
|
--
|
|||
|
|
-- Reads the persistent history via `jarvis.llm_history()`, builds a short
|
|||
|
|
-- recap prompt, asks the LLM. If there's no history yet or the LLM is
|
|||
|
|
-- unreachable, falls back to a polite "ничего не вспомнить" reply.
|
|||
|
|
|
|||
|
|
local lang = jarvis.context.language
|
|||
|
|
|
|||
|
|
local turns = jarvis.llm_history() or {}
|
|||
|
|
-- Take only the last 12 user/assistant turns to keep prompt small.
|
|||
|
|
local recent = {}
|
|||
|
|
local start = math.max(1, #turns - 11)
|
|||
|
|
for i = start, #turns do
|
|||
|
|
if turns[i] then table.insert(recent, turns[i]) end
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
if #recent == 0 then
|
|||
|
|
return jarvis.cmd.not_found(lang == "ru"
|
|||
|
|
and "Мы пока ещё ни о чём не говорили, сэр."
|
|||
|
|
or "We haven't talked about anything yet, sir.")
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
-- Render history as a compact "Пользователь: ... / Я: ..." dialogue.
|
|||
|
|
local lines = {}
|
|||
|
|
for _, m in ipairs(recent) do
|
|||
|
|
local who = m.role == "assistant" and (lang == "ru" and "Я" or "Me")
|
|||
|
|
or (lang == "ru" and "Пользователь" or "User")
|
|||
|
|
table.insert(lines, who .. ": " .. (m.content or ""))
|
|||
|
|
end
|
|||
|
|
local transcript = table.concat(lines, "\n")
|
|||
|
|
|
|||
|
|
local token = jarvis.system.env("GROQ_TOKEN")
|
|||
|
|
if not token or token == "" then
|
|||
|
|
-- Offline path: just speak the user's last message back briefly.
|
|||
|
|
return jarvis.cmd.ok(lang == "ru"
|
|||
|
|
and ("Без сети, сэр. Последний раз вы спросили: " .. (recent[#recent].content or ""):sub(1, 200))
|
|||
|
|
or ("No network, sir. Last topic: " .. (recent[#recent].content or ""):sub(1, 200)))
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
local base = jarvis.system.env("GROQ_BASE_URL")
|
|||
|
|
if not base or base == "" then base = "https://api.groq.com/openai/v1" end
|
|||
|
|
local model = jarvis.system.env("GROQ_MODEL")
|
|||
|
|
if not model or model == "" then model = "llama-3.3-70b-versatile" end
|
|||
|
|
|
|||
|
|
local sys
|
|||
|
|
if lang == "ru" then
|
|||
|
|
sys = "Ты — J.A.R.V.I.S. По ниже идущему диалогу с пользователем составь короткое "
|
|||
|
|
.. "напоминание (1-3 предложения), о чём шла речь. Говори от первого лица в "
|
|||
|
|
.. "стиле британского дворецкого. Не пересказывай дословно — сожми суть."
|
|||
|
|
else
|
|||
|
|
sys = "You are J.A.R.V.I.S. From the dialogue below, write a brief recap "
|
|||
|
|
.. "(1-3 sentences) of what we talked about. Use first person, British "
|
|||
|
|
.. "butler tone. Don't quote verbatim — distil the essence."
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
local payload = {
|
|||
|
|
model = model,
|
|||
|
|
messages = {
|
|||
|
|
{ role = "system", content = sys },
|
|||
|
|
{ role = "user", content = transcript },
|
|||
|
|
},
|
|||
|
|
max_tokens = 200,
|
|||
|
|
temperature = 0.4,
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
local res = jarvis.http.post_json(base .. "/chat/completions", payload,
|
|||
|
|
{ Authorization = "Bearer " .. token })
|
|||
|
|
if not res.ok then
|
|||
|
|
return jarvis.cmd.error(lang == "ru" and "LLM не отвечает." or "LLM didn't respond.")
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
local content = (res.body or ""):match('"content"%s*:%s*"(.-[^\\])"')
|
|||
|
|
if not content then
|
|||
|
|
return jarvis.cmd.error(lang == "ru" and "Не смог разобрать ответ." or "Couldn't parse reply.")
|
|||
|
|
end
|
|||
|
|
content = content:gsub('\\n', ' '):gsub('\\"', '"'):gsub('\\\\', '\\')
|
|||
|
|
content = content:gsub("%s+", " "):gsub("^%s+", ""):gsub("%s+$", "")
|
|||
|
|
|
|||
|
|
return jarvis.cmd.ok(content)
|