Mercurial Hosting > lang
diff src/lib/ai/claude/Ai_chat.luan @ 19:0351b3d474f8
minor
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Wed, 30 Jul 2025 15:28:09 -0600 |
parents | src/lib/ai/claude/Chat.luan@f5425a3c1898 |
children | 27989d63fc71 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib/ai/claude/Ai_chat.luan Wed Jul 30 15:28:09 2025 -0600 @@ -0,0 +1,129 @@ +local Luan = require "luan:Luan.luan" +local error = Luan.error +local ipairs = Luan.ipairs or error() +local type = Luan.type or error() +local String = require "luan:String.luan" +local starts_with = String.starts_with or error() +local Html = require "luan:Html.luan" +local html_encode = Html.encode or error() +local Parsers = require "luan:Parsers.luan" +local json_parse = Parsers.json_parse or error() +local json_string = Parsers.json_string or error() +local Claude = require "site:/lib/ai/claude/Claude.luan" +local claude_chat = Claude.chat or error() +local Logging = require "luan:logging/Logging.luan" +local logger = Logging.logger "claude/Ai_chat" + + +local Ai_chat = {} + +function Ai_chat.output_system_prompt(thread) + if thread == nil then + return + end + thread = json_parse(thread) + local system_prompt = thread.system or error + system_prompt = html_encode(system_prompt) + %><%=system_prompt%><% +end + +function Ai_chat.output_messages_html(lang,thread,old_thread) + if thread == nil then + return + end + thread = json_parse(thread) + local messages = thread.messages or error + local n = 0 + if old_thread ~= nil then + old_thread = json_parse(old_thread) + local old_messages = old_thread.messages or error + n = #old_messages + end + for i, message in ipairs(messages) do + if i <= n then + continue + end + local role = message.role or error() + local who + if role=="assistant" then + who = "Claude" + elseif role=="user" then + who = "You" + else + error(role) + end + local function output(text) + text = html_encode(text) +%> + <h3><%=who%></h3> + <div markdown role="<%=role%>" lang="<%=lang%>"><%=text%></div> +<% + end + local content = message.content or error() + if type(content) == "string" then + output(content) + else + for _, part in ipairs(content) do + if part.type=="text" then + local text = part.text or error() + output(text) + end + end + end + end_for +end + + +local system_prompt = [[ +CRITICAL REQUIREMENT: When writing Japanese, use ruby markdown syntax {japanese|romaji} for pronunciation guidance. + +Apply ruby tags to meaningful pronunciation units: +- Individual kanji or kanji compounds: {私|watashi}, {学生|gakusei} +- Hiragana/katakana words and particles: {は|wa}, {です|desu}, {ありがとう|arigatō} +- Grammatical elements: {ました|mashita}, {ません|masen} + +The romaji must reflect ACTUAL PRONUNCIATION, not character-by-character readings. +Use macrons for long vowels: ā, ī, ū, ē, ō + +APPLIES TO ALL JAPANESE TEXT: Example sentences, grammar explanations, vocabulary lists, casual mentions - ANY Japanese characters in your response need ruby tags. + +VERIFICATION STEP: Before sending, scan your ENTIRE response for any Japanese characters (hiragana, katakana, kanji) and ensure they all have ruby tags. +]] + + +function Ai_chat.ask(thread,input) + thread = thread and json_parse(thread) or { + system = system_prompt + messages = {nil} + } + local messages = thread.messages or error + messages[#messages+1] = { + role = "user" + content = input + } +--[=[ + messages[#messages+1] = { + role = "assistant" + content = [[ +hello +]] + } + if true then + return json_string(thread) + end +--]=] + local resultJson = claude_chat(thread) + local result = json_parse(resultJson) + -- logger.info(json_string(result)) + result.type == "message" or error() + result.role == "assistant" or error() + result.stop_reason == "end_turn" or result.stop_reason == "tool_use" or error() + local content = result.content or error() + messages[#messages+1] = { + role = "assistant" + content = content + } + return json_string(thread) +end + +return Ai_chat