← 모듈 공장 리스트

Korean Particle Helper

risum 모듈 — RISU modules[] — 기능 확장

🗒️ 제작자 게시글

자료원문 보기 ↗

조회 2235 · 2026-05-18

제작자 의도 — 본문 전문 (379자)
그건 바로
종원는 사과을 한 입 베어물었다.
"그래서, 서현가 보안실으로 향했다는 정보의 출처는?"
이런 조사 찐빠임
봇이나 프롬 프리셋, 혹은 퍼메에서 {{user}}를, {{user}}가, {{user}}는 이렇게 적어둔 경우 찐빠가 발생하는데
딥식은 맥락 의존도가 심해서 한국어 조사를 이해하는 상황에서도 이전 맥락이 조사가 찐빠난 상태면 이걸 그냥 따라가버리는 편향이 몹시 심함
그래서 만들어왔음,,,
복잡한건 없고 off 하면 꺼짐
Output하면 매 턴 아웃풋만 수정됨
Request+Output은 이전 맥락의 조사찐빠도 보정함(원래 하던 세션에 적용시킬때 이거 쓰면 됨)
https://drive.proton.me/urls/9936N3EZDW#ghIYWdyo5XnS

정체

🛠 기타·유틸기술분류 INPUT슬롯 inputKorean Particle Helper
파싱된 모듈 전체 (11,168자)
{
 "type": "risuModule",
 "name": "Korean Particle Helper",
 "id": "f1ea3a0f-9f3f-4c30-a6da-d251458f955a",
 "namespace": "korean_particle_helper",
 "description": "",
 "customModuleToggle": "=Korean Particle Helper=group\n조사치환=조사 치환=select=Off,Output,Request+Output",
 "trigger": [
  {
   "type": "start",
   "conditions": [],
   "effect": [
    {
     "type": "triggerlua",
     "code": "-- Korean Particle Risu module payload.\n-- Import through Korean_Particle_Module.json, not as a standalone Lua file.\n\nKoreanParticle = KoreanParticle or {}\n\nKoreanParticle.digit_batchim = {\n  [\"0\"] = true,  -- 영\n  [\"1\"] = true,  -- 일\n  [\"2\"] = false, -- 이\n  [\"3\"] = true,  -- 삼\n  [\"4\"] = false, -- 사\n  [\"5\"] = false, -- 오\n  [\"6\"] = true,  -- 육\n  [\"7\"] = true,  -- 칠\n  [\"8\"] = true,  -- 팔\n  [\"9\"] = false  -- 구\n}\n\nKoreanParticle.final_jamo_index = {\n  [0x3131]=1, [0x3132]=1, [0x3133]=1, [0x3134]=1, [0x3135]=1, [0x3136]=1,\n  [0x3137]=1, [0x3139]=8, [0x313A]=1, [0x313B]=1, [0x313C]=1, [0x313D]=1,\n  [0x313E]=1, [0x313F]=1, [0x3140]=1, [0x3141]=1, [0x3142]=1, [0x3144]=1,\n  [0x3145]=1, [0x3146]=1, [0x3147]=1, [0x3148]=1, [0x314A]=1, [0x314B]=1,\n  [0x314C]=1, [0x314D]=1, [0x314E]=1\n}\n\nKoreanParticle.trailing_ignore = {\n  [0x22]=true, [0x27]=true, [0x29]=true, [0x2C]=true, [0x2E]=true, [0x3A]=true,\n  [0x3B]=true, [0x3F]=true, [0x5D]=true, [0x60]=true, [0x7D]=true, [0x7E]=true,\n  [0x2019]=true, [0x201D]=true, [0x2026]=true, [0x3002]=true, [0x3009]=true,\n  [0x300B]=true, [0x300D]=true, [0x300F]=true, [0xFF01]=true, [0xFF0C]=true,\n  [0xFF1A]=true, [0xFF1B]=true, [0xFF1F]=true\n}\n\nKoreanParticle.particles = {\n  [\"은/는\"] = {\"은\", \"는\"},\n  [\"이/가\"] = {\"이\", \"가\"},\n  [\"을/를\"] = {\"을\", \"를\"},\n  [\"과/와\"] = {\"과\", \"와\"},\n  [\"아/야\"] = {\"아\", \"야\"},\n  [\"이야/야\"] = {\"이야\", \"야\"},\n  [\"이에요/예요\"] = {\"이에요\", \"예요\"},\n  [\"이랑/랑\"] = {\"이랑\", \"랑\"},\n  [\"으로/로\"] = {\"으로\", \"로\", \"rieulException\"}\n}\n\nKoreanParticle.auto_rules = {\n  {pair=\"이에요/예요\", variants={\"이에요\", \"예요\"}},\n  {pair=\"이랑/랑\", variants={\"이랑\", \"랑\"}},\n  {pair=\"으로/로\", variants={\"으로\", \"로\"}},\n  {pair=\"은/는\", variants={\"은\", \"는\"}},\n  {pair=\"이/가\", variants={\"이\", \"가\"}},\n  {pair=\"을/를\", variants={\"을\", \"를\"}},\n  {pair=\"과/와\", variants={\"과\", \"와\"}},\n  {pair=\"아/야\", variants={\"아\", \"야\"}}\n}\n\nfunction KoreanParticle.read_codepoint(text, index)\n  local b1 = string.byte(text, index)\n  if b1 == nil then return nil, index end\n  if b1 < 0x80 then return b1, index + 1 end\n  local b2 = string.byte(text, index + 1) or 0\n  if b1 < 0xE0 then\n    return ((b1 % 0x20) * 0x40) + (b2 % 0x40), index + 2\n  end\n  local b3 = string.byte(text, index + 2) or 0\n  if b1 < 0xF0 then\n    return ((b1 % 0x10) * 0x1000) + ((b2 % 0x40) * 0x40) + (b3 % 0x40), index + 3\n  end\n  local b4 = string.byte(text, index + 3) or 0\n  return ((b1 % 0x08) * 0x40000) + ((b2 % 0x40) * 0x1000) + ((b3 % 0x40) * 0x40) + (b4 % 0x40), index + 4\nend\n\nfunction KoreanParticle.is_trailing_ignore(code)\n  if code == nil then return true end\n  if code <= 0x20 then return true end\n  return KoreanParticle.trailing_ignore[code] == true\nend\n\nfunction KoreanParticle.last_codepoint(value)\n  local text = tostring(value or \"\")\n  local codes = {}\n  local i = 1\n  while i <= #text do\n    local code, next_i = KoreanParticle.read_codepoint(text, i)\n    if code == nil then break end\n    codes[#codes + 1] = code\n    if next_i <= i then break end\n    i = next_i\n  end\n  for j=#codes,1,-1 do\n    if not KoreanParticle.is_trailing_ignore(codes[j]) then\n      return codes[j]\n    end\n  end\n  return 0\nend\n\nfunction KoreanParticle.final_index(value)\n  local code = KoreanParticle.last_codepoint(value)\n  if code >= 0xAC00 and code <= 0xD7A3 then\n    return (code - 0xAC00) % 28\n  end\n  if code >= 0x11A8 and code <= 0x11C2 then return 1 end\n  if KoreanParticle.final_jamo_index[code] ~= nil then return KoreanParticle.final_jamo_index[code] end\n  if code >= 0x30 and code <= 0x39 then\n    local ch = string.char(code)\n    if KoreanParticle.digit_batchim[ch] then return 1 end\n    return 0\n  end\n  return 0\nend\n\nfunction KoreanParticle.has_batchim(value)\n  return KoreanParticle.final_index(value) > 0\nend\n\nfunction KoreanParticle.has_rieul_batchim(value)\n  return KoreanParticle.final_index(value) == 8\nend\n\nfunction KoreanParticle.rule(pair)\n  local key = tostring(pair or \"\")\n  local known = KoreanParticle.particles[key]\n  if known ~= nil then return known end\n  local a, b = key:match(\"^([^/]+)/([^/]+)$\")\n  if a ~= nil and b ~= nil and a ~= \"\" and b ~= \"\" then return {a, b} end\n  error(\"Unsupported Korean particle pair: \"..key)\nend\n\nfunction KoreanParticle.particle(value, pair)\n  local rule = KoreanParticle.rule(pair)\n  if rule[3] == \"rieulException\" then\n    if KoreanParticle.has_batchim(value) and not KoreanParticle.has_rieul_batchim(value) then\n      return rule[1]\n    end\n    return rule[2]\n  end\n  if KoreanParticle.has_batchim(value) then return rule[1] end\n  return rule[2]\nend\n\nfunction KoreanParticle.attach(value, pair)\n  return tostring(value or \"\")..KoreanParticle.particle(value, pair)\nend\n\nfunction KoreanParticle.format(template, values)\n  local data = values or {}\n  local text = tostring(template or \"\")\n  return text:gsub(\"{([%w_.-]+):([^{}]+)}\", function(key, pair)\n    local current = data\n    for part in key:gmatch(\"[^.]+\") do\n      if type(current) ~= \"table\" then current = nil break end\n      current = current[part]\n    end\n    return KoreanParticle.attach(current or \"\", pair)\n  end)\nend\n\nfunction KoreanParticle.split_chars(text)\n  local chars = {}\n  local codes = {}\n  local i = 1\n  while i <= #text do\n    local code, next_i = KoreanParticle.read_codepoint(text, i)\n    if code == nil then break end\n    chars[#chars + 1] = text:sub(i, next_i - 1)\n    codes[#codes + 1] = code\n    if next_i <= i then break end\n    i = next_i\n  end\n  return chars, codes\nend\n\nfunction KoreanParticle.prepare_auto_rules()\n  if KoreanParticle.auto_rules_prepared then return end\n  for _, rule in ipairs(KoreanParticle.auto_rules) do\n    rule.variant_chars = {}\n    for _, variant in ipairs(rule.variants) do\n      local chars = KoreanParticle.split_chars(variant)\n      rule.variant_chars[#rule.variant_chars + 1] = {text=variant, chars=chars, len=#chars}\n    end\n  end\n  KoreanParticle.auto_rules_prepared = true\nend\n\nfunction KoreanParticle.is_token_code(code)\n  if code == nil then return false end\n  if code >= 0xAC00 and code <= 0xD7A3 then return true end\n  if code >= 0x1100 and code <= 0x11FF then return true end\n  if code >= 0x3130 and code <= 0x318F then return true end\n  if code >= 0x4E00 and code <= 0x9FFF then return true end\n  if code >= 0x3040 and code <= 0x30FF then return true end\n  if code >= 0x30 and code <= 0x39 then return true end\n  if code >= 0x41 and code <= 0x5A then return true end\n  if code >= 0x61 and code <= 0x7A then return true end\n  if code == 0x5F then return true end\n  return false\nend\n\nfunction KoreanParticle.is_boundary_code(code)\n  return not KoreanParticle.is_token_code(code)\nend\n\nfunction KoreanParticle.match_chars(chars, index, variant)\n  for offset = 1, variant.len do\n    if chars[index + offset - 1] ~= variant.chars[offset] then return false end\n  end\n  return true\nend\n\nfunction KoreanParticle.token_before(chars, codes, index)\n  local j = index - 1\n  while j >= 1 and KoreanParticle.is_token_code(codes[j]) do\n    j = j - 1\n  end\n  if j == index - 1 then return nil end\n  return table.concat(chars, \"\", j + 1, index - 1)\nend\n\nfunction KoreanParticle.skip_auto_context(chars, codes, index)\n  local previous = codes[index - 1]\n  if previous == nil then return true end\n  if previous == 0x3C or previous == 0x2F then return true end\n  return false\nend\n\nfunction KoreanParticle.correct_plain_text(text)\n  if type(text) ~= \"string\" or text == \"\" then return text end\n  KoreanParticle.prepare_auto_rules()\n\n  local chars, codes = KoreanParticle.split_chars(text)\n  local result = {}\n  local i = 1\n\n  while i <= #chars do\n    if chars[i] == \"<\" then\n      while i <= #chars do\n        result[#result + 1] = chars[i]\n        if chars[i] == \">\" then\n          i = i + 1\n          break\n        end\n        i = i + 1\n      end\n    else\n      local replaced = false\n      for _, rule in ipairs(KoreanParticle.auto_rules) do\n        if not replaced then\n          for _, variant in ipairs(rule.variant_chars) do\n            if KoreanParticle.match_chars(chars, i, variant) and\n              KoreanParticle.is_boundary_code(codes[i + variant.len]) and\n              not KoreanParticle.skip_auto_context(chars, codes, i) then\n              local stem = KoreanParticle.token_before(chars, codes, i)\n              if stem ~= nil and stem ~= \"\" then\n                local ok, correct = pcall(function()\n                  return KoreanParticle.particle(stem, rule.pair)\n                end)\n                if ok then\n                  result[#result + 1] = correct\n                  i = i + variant.len\n                  replaced = true\n                  break\n                end\n              end\n            end\n          end\n        end\n      end\n      if not replaced then\n        result[#result + 1] = chars[i]\n        i = i + 1\n      end\n    end\n  end\n\n  return table.concat(result)\nend\n\nlocal function kp_mode(id)\n  local value = tostring(getGlobalVar(id, \"toggle_조사치환\") or \"\")\n  if value == \"\" or value == \"0\" or value == \"Off\" or value == \"off\" or value == \"nil\" then return \"off\" end\n  if value == \"1\" or value == \"Output\" or value == \"출력\" then return \"output\" end\n  if value == \"2\" or value == \"Request+Output\" or value == \"요청+출력\" then return \"request_output\" end\n  return \"off\"\nend\n\nfunction KoreanParticle.normalize_text(id, text)\n  return KoreanParticle.correct_plain_text(text)\nend\n\nKP_PARTICLE = function(value, pair) return KoreanParticle.particle(value, pair) end\nKP_ATTACH = function(value, pair) return KoreanParticle.attach(value, pair) end\nKP_FORMAT = function(template, values) return KoreanParticle.format(template, values) end\nKP_CORRECT_TEXT = function(text) return KoreanParticle.correct_plain_text(text) end\n\nlistenEdit(\"editOutput\", function(id, data, meta)\n  local mode = kp_mode(id)\n  if mode == \"off\" then return data end\n  return KoreanParticle.normalize_text(id, data)\nend)\n\nlistenEdit(\"editRequest\", function(id, data, meta)\n  local mode = kp_mode(id)\n  if mode ~= \"request_output\" then return data end\n  if type(data) ~= \"table\" then return data end\n  for i = 1, #data do\n    local msg = data[i]\n    if type(msg) == \"table\" and type(msg.content) == \"string\" then\n      msg.content = KoreanParticle.normalize_text(id, msg.content)\n    end\n  end\n  return data\nend)\n"
    }
   ],
   "lowLevelAccess": false
  }
 ],
 "hideIcon": false,
 "lorebook": [],
 "regex": [],
 "lowLevelAccess": false,
 "assets": []
}

🔗 이것과 비슷한 인기 자산

💗 S.M.A.F.M.S
반드시 파츠 토글을 활성화하세요! / Must enable the parts toggle!
👍82 ·
아이네 전용 모듈 V7
※중요! 1. 딥식의 경우 추론 파라미터 'none'을 기준으로 테스트되었습니다 2. '반복 부수기 활성화' 토글은 사실상 프롬의 핵심 기능에 복합적으로 엮여 있으니 켜는 걸 적극 권장 소개 - 시간 흐름 정상화(시
👍61 ·
🎲 MGH Caffee_V2
'/게임목록', '/GAMELIST'을 입력하면 게임 목록이 출력됩니다.
👍52 ·
구동요정 아이딜
분양용 모듈
👍48 ·
🐞 W2 · /city/asset