๋ณธ๋ฌธ์œผ๋กœ ๊ฑด๋„ˆ๋›ฐ๊ธฐ

๐Ÿช„ ํ•„ํ„ฐ ๊ธฐ๋Šฅ: ์ž…๋ ฅ ๋ฐ ์ถœ๋ ฅ ์ˆ˜์ •

Open WebUI์—์„œ ํ•„ํ„ฐ ๊ธฐ๋Šฅ์— ๋Œ€ํ•œ ์ข…ํ•ฉ์ ์ธ ๊ฐ€์ด๋“œ์— ์˜ค์‹  ๊ฒƒ์„ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค! ํ•„ํ„ฐ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ **๋Œ€๊ทœ๋ชจ ์–ธ์–ด ๋ชจ๋ธ(LLM)**์— ๋ณด๋‚ด๊ธฐ ์ „(์ž…๋ ฅ) ๋˜๋Š” **LLM๋กœ๋ถ€ํ„ฐ ๋ฐ˜ํ™˜๋œ ํ›„(์ถœ๋ ฅ)**์— ์ˆ˜์ •ํ•˜๋Š” ์œ ์—ฐํ•˜๊ณ  ๊ฐ•๋ ฅํ•œ ํ”Œ๋Ÿฌ๊ทธ์ธ ์‹œ์Šคํ…œ์ž…๋‹ˆ๋‹ค. ์ž…๋ ฅ์„ ๋” ๋‚˜์€ ์ปจํ…์ŠคํŠธ๋กœ ๋ณ€ํ™˜ํ•˜๊ฑฐ๋‚˜ ์ถœ๋ ฅ์„ ๋” ์ฝ๊ธฐ ์‰ฝ๊ฒŒ ์ •๋ฆฌํ•˜๋Š” ๋“ฑ ํ•„ํ„ฐ ๊ธฐ๋Šฅ์œผ๋กœ ๋ชจ๋“  ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ๊ฐ€์ด๋“œ๋Š” ํ•„ํ„ฐ๋ž€ ๋ฌด์—‡์ธ์ง€, ํ•„ํ„ฐ๊ฐ€ ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€, ๊ทธ ๊ตฌ์กฐ๋ฅผ ํฌํ•จํ•˜์—ฌ ๊ฐ•๋ ฅํ•˜๊ณ  ์‚ฌ์šฉ์ž ์นœํ™”์ ์ธ ํ•„ํ„ฐ๋ฅผ ์ง์ ‘ ๊ตฌ์ถ•ํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ๋ชจ๋“  ์ •๋ณด๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ๋น„์œ , ์˜ˆ์‹œ ๋ฐ ํŒ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ชจ๋“  ๊ฒƒ์„ ์‰ฝ๊ฒŒ ์„ค๋ช…ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ๐ŸŒŸ


๐ŸŒŠ Open WebUI์˜ ํ•„ํ„ฐ๋ž€?โ€‹

Open WebUI๋ฅผ ํŒŒ์ดํ”„๋ฅผ ํ†ตํ•ด ํ๋ฅด๋Š” ๋ฌผ๋กœ ์ƒ์ƒํ•ด๋ณด์„ธ์š”:

  • ์‚ฌ์šฉ์ž ์ž…๋ ฅ๊ณผ LLM ์ถœ๋ ฅ์€ ๋ฌผ์ž…๋‹ˆ๋‹ค.
  • ํ•„ํ„ฐ๋Š” ๋ฌผ์ด ์ตœ์ข… ๋ชฉ์ ์ง€์— ๋„๋‹ฌํ•˜๊ธฐ ์ „์— ๋ฌผ์„ ์ฒญ์†Œ, ์ˆ˜์ • ๋ฐ ์ ์‘์‹œํ‚ค๋Š” ๋ฌผ ์ฒ˜๋ฆฌ ๋‹จ๊ณ„์ž…๋‹ˆ๋‹ค.

ํ•„ํ„ฐ๋Š” ํ๋ฆ„ ์ค‘๊ฐ„์— ์œ„์น˜ํ•˜์—ฌ ์กฐ์ •ํ•ด์•ผ ํ•  ์‚ฌํ•ญ์„ ๊ฒฐ์ •ํ•  ์ˆ˜ ์žˆ๋Š” ์ฒดํฌํฌ์ธํŠธ ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ์€ ํ•„ํ„ฐ๊ฐ€ ์ˆ˜ํ–‰ํ•˜๋Š” ์ž‘์—…์— ๋Œ€ํ•œ ์š”์•ฝ์ž…๋‹ˆ๋‹ค:

  1. ์‚ฌ์šฉ์ž ์ž…๋ ฅ ์ˆ˜์ •(Inlet Function): AI ๋ชจ๋ธ์— ๋„๋‹ฌํ•˜๊ธฐ ์ „์— ์ž…๋ ฅ ๋ฐ์ดํ„ฐ๋ฅผ ์กฐ์ •ํ•ฉ๋‹ˆ๋‹ค. ๋ช…ํ™•์„ฑ์„ ๋†’์ด๊ฑฐ๋‚˜, ์ปจํ…์ŠคํŠธ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜, ํ…์ŠคํŠธ๋ฅผ ์ •๋ฆฌํ•˜๊ฑฐ๋‚˜, ํŠน์ • ์š”๊ตฌ์‚ฌํ•ญ์— ๋งž๊ฒŒ ๋ฉ”์‹œ์ง€๋ฅผ ๋‹ค์‹œ ํฌ๋งทํ•˜๋Š” ๊ธฐ๋Šฅ์ด ์—ฌ๊ธฐ์—์„œ ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค.
  2. ๋ชจ๋ธ ์ถœ๋ ฅ ๊ฐ€๋กœ์ฑ„๊ธฐ(Stream Function): ๋ชจ๋ธ์ด ์ƒ์„ฑํ•˜๋Š” ์ค‘์˜ AI ์‘๋‹ต์„ ์บก์ฒ˜ํ•˜๊ณ  ์กฐ์ •ํ•ฉ๋‹ˆ๋‹ค. ์‹ค์‹œ๊ฐ„ ์ˆ˜์ •์— ์œ ์šฉํ•˜๋ฉฐ, ๋ฏผ๊ฐํ•œ ์ •๋ณด๋ฅผ ํ•„ํ„ฐ๋งํ•˜๊ฑฐ๋‚˜ ์ถœ๋ ฅ์„ ๋” ์ฝ๊ธฐ ์‰ฝ๊ฒŒ ํฌ๋งทํ•˜๋Š” ๋ฐ ํ™œ์šฉ๋ฉ๋‹ˆ๋‹ค.
  3. ๋ชจ๋ธ ์ถœ๋ ฅ ์ˆ˜์ •(Outlet Function): ์ฒ˜๋ฆฌ๋œ ํ›„์˜ AI ์‘๋‹ต์„ ์กฐ์ •ํ•˜์—ฌ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ณด์—ฌ์ฃผ๊ธฐ ์ „์— ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ์„ธ๋ จ๋˜๊ฒŒ ๋‹ค๋“ฌ๊ณ , ๋กœ๊ทธ๋ฅผ ๋‚จ๊ธฐ๊ฑฐ๋‚˜, ๋” ๊นจ๋—ํ•œ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์„ ์œ„ํ•ด ๋ฐ์ดํ„ฐ์— ๋ณ€ํ™”๋ฅผ ์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ•ต์‹ฌ ๊ฐœ๋…: ํ•„ํ„ฐ๋Š” ๋…๋ฆฝ์ ์ธ ๋ชจ๋ธ์ด ์•„๋‹ˆ๋ผ ๋ชจ๋ธ๋กœ ์ „์†ก๋˜๊ณ  ๋ชจ๋ธ์—์„œ ๋ฐ˜ํ™˜๋˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ํ–ฅ์ƒํ•˜๊ฑฐ๋‚˜ ๋ณ€ํ™˜ํ•˜๋Š” ๋„๊ตฌ์ž…๋‹ˆ๋‹ค.

ํ•„ํ„ฐ๋Š” AI ์›Œํฌํ”Œ๋กœ์šฐ์—์„œ ๋ฒˆ์—ญ๊ธฐ ๋˜๋Š” ํŽธ์ง‘์ž์™€ ๊ฐ™์œผ๋ฉฐ, ํ๋ฆ„์„ ์ค‘๋‹จํ•˜์ง€ ์•Š๊ณ  ๋Œ€ํ™”๋ฅผ ๊ฐ€๋กœ์ฑ„๊ณ  ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


๐Ÿ—บ๏ธ ํ•„ํ„ฐ ๊ธฐ๋Šฅ์˜ ๊ตฌ์กฐ: ์Šค์ผˆ๋ ˆํ†คโ€‹

ํ•„ํ„ฐ ๊ธฐ๋Šฅ์˜ ๊ฐ€์žฅ ๊ฐ„๋‹จํ•œ ํ‘œํ˜„๋ถ€ํ„ฐ ์‹œ์ž‘ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ฒ˜์Œ์—๋Š” ๊ธฐ์ˆ ์ ์œผ๋กœ ๋А๊ปด์งˆ ์ˆ˜ ์žˆ์ง€๋งŒ ๋ชจ๋“  ๋ถ€๋ถ„์„ ๋‹จ๊ณ„๋ณ„๋กœ ์„ค๋ช…ํ•˜๋‹ˆ ๊ฑฑ์ •ํ•˜์ง€ ๋งˆ์„ธ์š”!

๐Ÿฆด ํ•„ํ„ฐ์˜ ๊ธฐ๋ณธ ์Šค์ผˆ๋ ˆํ†คโ€‹

from pydantic import BaseModel
from typing import Optional

class Filter:
# ๋ฐธ๋ธŒ: ํ•„ํ„ฐ๋ฅผ ์œ„ํ•œ ์„ค์ • ์˜ต์…˜
class Valves(BaseModel):
pass

def __init__(self):
# ๋ฐธ๋ธŒ ์ดˆ๊ธฐํ™”(ํ•„ํ„ฐ๋ฅผ ์œ„ํ•œ ์„ ํƒ์  ์„ค์ •)
self.valves = self.Valves()

def inlet(self, body: dict) -> dict:
# ์—ฌ๊ธฐ์—์„œ ์‚ฌ์šฉ์ž ์ž…๋ ฅ์„ ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค.
print(f"inlet ํ˜ธ์ถœ๋จ: {body}")
return body

def stream(self, event: dict) -> dict:
# ์—ฌ๊ธฐ์—์„œ ๋ชจ๋ธ ์ถœ๋ ฅ์˜ ์ŠคํŠธ๋ฆฌ๋ฐ ์ฒญํฌ๋ฅผ ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค.
print(f"stream ์ด๋ฒคํŠธ: {event}")
return event

def outlet(self, body: dict) -> None:
# ์—ฌ๊ธฐ์—์„œ ๋ชจ๋ธ ์ถœ๋ ฅ์„ ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค.
print(f"outlet ํ˜ธ์ถœ๋จ: {body}")

๐Ÿ†• ๐Ÿงฒ ํ† ๊ธ€ ํ•„ํ„ฐ ์˜ˆ์‹œ: ์ธํ„ฐ๋ž™ํ‹ฐ๋ธŒ ๊ธฐ๋Šฅ ๋ฐ ์•„์ด์ฝ˜ ์ถ”๊ฐ€ (Open WebUI 0.6.10 ์‹ ๊ทœ ๊ธฐ๋Šฅ)โ€‹

ํ•„ํ„ฐ๋Š” ํ…์ŠคํŠธ ์ˆ˜์ • ์ด์ƒ์˜ ๊ธฐ๋Šฅ์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹คโ€”UI ํ† ๊ธ€์„ ๋…ธ์ถœํ•˜๊ฑฐ๋‚˜ ์ปค์Šคํ…€ ์•„์ด์ฝ˜์„ ํ‘œ์‹œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ํ•„ํ„ฐ๋ฅผ ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค ๋ฒ„ํŠผ์œผ๋กœ ์ผœ๊ฑฐ๋‚˜ ๋Œ ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๊ณ  Open WebUI์˜ ๋ฉ”์‹œ์ง€ ์ž…๋ ฅ UI์— ํŠน๋ณ„ํ•œ ์•„์ด์ฝ˜์„ ํ‘œ์‹œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ์€ ํ•ด๋‹น ํ† ๊ธ€ ํ•„ํ„ฐ๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค:

from pydantic import BaseModel, Field
from typing import Optional

class Filter:
class Valves(BaseModel):
pass

def __init__(self):
self.valves = self.Valves()
self.toggle = True # ์ค‘์š”: Open WebUI์—์„œ ์Šค์œ„์น˜ UI ์ƒ์„ฑ
# ํŒ: SVG ๋ฐ์ดํ„ฐ URI๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”!
self.icon = """data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCAyNCAyNCIgc3Ryb2tlLXdpZHRoPSIxLjUiIHN0cm9rZT0iY3VycmVudENvbG9yIiBjbGFzcz0ic2l6ZS02Ij4KICA8cGF0aCBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGQ9Ik0xMiAxOHYtNS4yNW0wIDBhNi4wMSA2LjAxIDAgMCAwIDEuNS0uMTg5bS0xLjUuMTg5YTYuMDEgNi4wMSAwIDAgMS0xLjUtLjE4OW0zLjc1IDcuNDc4YTEyLjA2IDEyLjA2IDAgMCAxLTQuNSAwbTMuNzUgMi4zODNhMTQuNDA2IDE0LjQwNiAwIDAgMS0zIDBNMTQuMjUgMTh2LS4xOTJjMC0uOTgzLjY1OC0xLjgyMyAxLjUwOC0yLjMxNmE3LjUgNy41IDAgMTAgLTcuNTE3IDBjLjg1LjQ5MyAxLjUwOSAxLjMzMyAxLjUwOSAyLjMxNlYxOCIgLz4KPC9zdmc+Cg=="""
pass

async def inlet(
self, body: dict, __event_emitter__, __user__: Optional[dict] = None
) -> dict:
await __event_emitter__(
{
"type": "status",
"data": {
"description": "ํ† ๊ธ€๋จ!",
"done": True
"hidden": False,
},
}
)
return body

๐Ÿ–ผ๏ธ ๋ฌด์Šจ ์ผ์ด ์ผ์–ด๋‚˜๊ณ  ์žˆ๋‚˜์š”?โ€‹

  • toggle = True๋Š” Open WebUI์—์„œ ์ „ํ™˜ UI๋ฅผ ์ƒ์„ฑํ•˜๋ฉฐ, ์‚ฌ์šฉ์ž๊ฐ€ ์‹ค์‹œ๊ฐ„์œผ๋กœ ํ•„ํ„ฐ๋ฅผ ์ˆ˜๋™์œผ๋กœ ํ™œ์„ฑํ™”ํ•˜๊ฑฐ๋‚˜ ๋น„ํ™œ์„ฑํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • icon(Data URI ํฌํ•จ)์€ ํ•„ํ„ฐ ์ด๋ฆ„ ์˜†์— ์ž‘์€ ์ด๋ฏธ์ง€๋กœ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. Data URI๋กœ ์ธ์ฝ”๋”ฉ๋œ SVG๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค!
  • inlet ํ•จ์ˆ˜๋Š” __event_emitter__ ํŠน๋ณ„ ์ธ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ UI์— ๋Œ€ํ•œ ํ”ผ๋“œ๋ฐฑ/์ƒํƒœ๋ฅผ ์•Œ๋ฆฝ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด "์ „ํ™˜๋จ!"์ด๋ผ๋Š” ์ž‘์€ ํ† ์ŠคํŠธ/์•Œ๋ฆผ์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

Toggle Filter

์ด๋Ÿฌํ•œ ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ์‚ฌ์šฉํ•˜์—ฌ ํ•„ํ„ฐ๋ฅผ ๋™์ ์ด๊ณ , ๋Œ€ํ™”ํ˜•์ด๋ฉฐ, Open WebUI์˜ ํ”Œ๋Ÿฌ๊ทธ์ธ ์ƒํƒœ๊ณ„ ๋‚ด์—์„œ ๋…์ฐฝ์ ์œผ๋กœ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


๐ŸŽฏ ์ฃผ์š” ๊ตฌ์„ฑ ์š”์†Œ ์„ค๋ช…โ€‹

1๏ธโƒฃ Valves ํด๋ž˜์Šค (์˜ต์…˜ ์„ค์ •)โ€‹

Valves๋ฅผ ํ•„ํ„ฐ์˜ ์กฐ์ • ๋…ธ๋ธŒ์™€ ์Šฌ๋ผ์ด๋”๋ผ๊ณ  ์ƒ๊ฐํ•˜์‹ญ์‹œ์˜ค. ํ•„ํ„ฐ ๋™์ž‘์„ ์‚ฌ์šฉ์ž๊ฐ€ ์กฐ์ • ๊ฐ€๋Šฅํ•œ ์˜ต์…˜์œผ๋กœ ์ œ๊ณตํ•˜๋ ค๋ฉด ์—ฌ๊ธฐ์— ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.

class Valves(BaseModel):
OPTION_NAME: str = "Default Value"

์˜ˆ์‹œ:
๋Œ€๋ฌธ์ž๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ํ•„ํ„ฐ๋ฅผ ๋งŒ๋“ค๊ณ  ์žˆ๊ณ , ๋ชจ๋“  ์ถœ๋ ฅ์ด ์™„์ „ํžˆ ๋Œ€๋ฌธ์ž์ธ์ง€ ์—ฌ๋ถ€๋ฅผ ์‚ฌ์šฉ์ž๊ฐ€ ์„ ํƒํ•˜๋„๋ก ํ•˜๋ ค๋Š” ๊ฒฝ์šฐ, TRANSFORM_UPPERCASE: bool = True/False์™€ ๊ฐ™์€ ๋ฐธ๋ธŒ๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


2๏ธโƒฃ inlet ํ•จ์ˆ˜ (์ž…๋ ฅ ์ „์ฒ˜๋ฆฌ)โ€‹

inlet ํ•จ์ˆ˜๋Š” ์š”๋ฆฌ์— ์žฌ๋ฃŒ๋ฅผ ์ค€๋น„ํ•˜๋Š” ๊ณผ์ •๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์š”๋ฆฌ์‚ฌ๋ผ๊ณ  ์ƒ์ƒํ•ด๋ณด์„ธ์š”: ๋ ˆ์‹œํ”ผ(์ด ๊ฒฝ์šฐ LLM)์— ์žฌ๋ฃŒ๋ฅผ ๋„ฃ๊ธฐ ์ „์— ์ฑ„์†Œ๋ฅผ ์”ป๊ณ , ์–‘ํŒŒ๋ฅผ ์ž๋ฅด๊ณ , ๊ณ ๊ธฐ์— ์–‘๋…์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ณผ์ •์ด ์—†๋‹ค๋ฉด ์ตœ์ข… ์š”๋ฆฌ๊ฐ€ ๋ถ€์กฑํ•œ ๋ง›์ด๊ฑฐ๋‚˜, ์”ป์ง€ ์•Š์€ ์žฌ๋ฃŒ๋ฅผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜, ์ผ๊ด€์„ฑ์ด ์—†์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Open WebUI์˜ ์„ธ๊ณ„์—์„œ๋Š”, inlet ํ•จ์ˆ˜๊ฐ€ ๋ชจ๋ธ์— ์ „๋‹ฌ๋˜๊ธฐ ์ „์— ์‚ฌ์šฉ์ž ์ž…๋ ฅ์— ๋Œ€ํ•ด ์ด๋Ÿฐ ์ค‘์š”ํ•œ ์ค€๋น„ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. ์ž…๋ ฅ์„ AI๊ฐ€ ์ฒ˜๋ฆฌํ•˜๊ธฐ์— ์ตœ๋Œ€ํ•œ ๊น”๋”ํ•˜๊ณ , ๋งฅ๋ฝ์ ์ด๋ฉฐ, ๋„์›€์ด ๋˜๋Š” ํ˜•ํƒœ๋กœ ์ •๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ“ฅ ์ž…๋ ฅ:

  • body: ๋ชจ๋ธ์— ๋Œ€ํ•œ Open WebUI์˜ ์›๋ณธ ์ž…๋ ฅ. ์ฑ„ํŒ… ์™„๋ฃŒ ์š”์ฒญ ํ˜•์‹(๋Œ€ํ™” ๋ฉ”์‹œ์ง€, ๋ชจ๋ธ ์„ค์ •, ๊ธฐํƒ€ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ๋“ฑ ํฌํ•จ๋œ ์‚ฌ์ „ ํ˜•์‹)์ž…๋‹ˆ๋‹ค. ์ด๋ฅผ ์š”๋ฆฌ ์žฌ๋ฃŒ๋ผ๊ณ  ์ƒ๊ฐํ•˜์‹ญ์‹œ์˜ค.

๐Ÿš€ ํ•  ์ผ:
body๋ฅผ ์ˆ˜์ •ํ•˜๊ณ  ๋ฐ˜ํ™˜ํ•˜์‹ญ์‹œ์˜ค. ์ˆ˜์ •๋œ body๊ฐ€ LLM๊ณผ ์ž‘์—…ํ•˜๊ฒŒ ๋˜๋ฏ€๋กœ, ์ด ๊ธฐํšŒ๋ฅผ ํ†ตํ•ด ์ž…๋ ฅ์— ๋ช…ํ™•์„ฑ, ๊ตฌ์กฐ, ๋งฅ๋ฝ์„ ๋ถ€์—ฌํ•˜์‹ญ์‹œ์˜ค.

๐Ÿณ inlet์„ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ ?โ€‹
  1. ๋งฅ๋ฝ ์ถ”๊ฐ€: ์‚ฌ์šฉ์ž์˜ ์ž…๋ ฅ์ด ๋ชจํ˜ธํ•˜๊ฑฐ๋‚˜ ๋ถˆ์™„์ „ํ•œ ๊ฒฝ์šฐ ์ค‘์š”ํ•œ ์ •๋ณด๋ฅผ ์ž๋™์œผ๋กœ ์ถ”๊ฐ€. ์˜ˆ๋ฅผ ๋“ค์–ด "๋‹น์‹ ์€ ์นœ์ ˆํ•œ ๋„์šฐ๋ฏธ์ž…๋‹ˆ๋‹ค" ๋˜๋Š” "์ด ์‚ฌ์šฉ์ž๊ฐ€ ์†Œํ”„ํŠธ์›จ์–ด ๋ฌธ์ œ ํ•ด๊ฒฐ์„ ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ฃผ์„ธ์š”"๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  2. ๋ฐ์ดํ„ฐ ํ˜•์‹ ์ง€์ •: ์ž…๋ ฅ์ด ํŠน์ • ํ˜•์‹(JSON ๋˜๋Š” Markdown)์„ ํ•„์š”๋กœ ํ•˜๋Š” ๊ฒฝ์šฐ, ๋ชจ๋ธ์— ๋ณด๋‚ด๊ธฐ ์ „์— ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  3. ์ž…๋ ฅ ์ •ํ™”: ๋ถˆํ•„์š”ํ•œ ๋ฌธ์ž ์ œ๊ฑฐ, ๊ณผ๋„ํ•œ ๊ณต๋ฐฑ ๋˜๋Š” ์ด๋ชจ์ง€์™€ ๊ฐ™์€ ํ˜ผ๋ž€์„ ์ค„ ์ˆ˜ ์žˆ๋Š” ๊ธฐํ˜ธ ์ œ๊ฑฐ, ๋ฏผ๊ฐํ•œ ์ •๋ณด ๊ต์ฒด.

  4. ์‚ฌ์šฉ์ž ์ž…๋ ฅ ๊ฐ„์†Œํ™”: ๋ชจ๋ธ ์ถœ๋ ฅ์ด ์ถ”๊ฐ€ ์ง€์นจ์œผ๋กœ ๊ฐœ์„ ๋˜๋Š” ๊ฒฝ์šฐ, inlet์„ ์‚ฌ์šฉํ•ด ๋ช…ํ™•ํ•œ ์ง€์‹œ๋ฅผ ์ž๋™์œผ๋กœ ์‚ฝ์ž…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค!

๐Ÿ’ก ์˜ˆ์‹œ ์‚ฌ์šฉ ์‚ฌ๋ก€: ์‹ํ’ˆ ์ค€๋น„ ๊ธฐ๋ฐ˜โ€‹
๐Ÿฅ— ์˜ˆ์ œ 1: ์‹œ์Šคํ…œ ์ปจํ…์ŠคํŠธ ์ถ”๊ฐ€โ€‹

LLM์ด ์ดํƒˆ๋ฆฌ์•„ ์š”๋ฆฌ๋ฅผ ์ค€๋น„ํ•˜๋Š” ์š”๋ฆฌ์‚ฌ์ด๋ฉฐ, ์‚ฌ์šฉ์ž๊ฐ€ "์ด๊ฒƒ์€ ์ดํƒˆ๋ฆฌ์•„ ์š”๋ฆฌ๋ฅผ ์œ„ํ•œ ๊ฒƒ"์ด๋ผ๊ณ  ์–ธ๊ธ‰ํ•˜์ง€ ์•Š์•˜๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ณด์„ธ์š”. ๋ฐ์ดํ„ฐ๋ฅผ ๋ชจ๋ธ๋กœ ๋ณด๋‚ด๊ธฐ ์ „์— ์ด ์ปจํ…์ŠคํŠธ๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ๋ฉ”์‹œ์ง€๊ฐ€ ๋ช…ํ™•ํ•œ์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

def inlet(self, body: dict, __user__: Optional[dict] = None) -> dict:
# ๋Œ€ํ™”์—์„œ ์ดํƒˆ๋ฆฌ์•„ ์ปจํ…์ŠคํŠธ์— ๋Œ€ํ•œ ์‹œ์Šคํ…œ ๋ฉ”์‹œ์ง€ ์ถ”๊ฐ€
context_message = {
"role": "system",
"content": "์‚ฌ์šฉ์ž๊ฐ€ ์ดํƒˆ๋ฆฌ์•„ ์š”๋ฆฌ๋ฅผ ์ค€๋น„ํ•˜๋„๋ก ๋•๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค."
}
# ๋Œ€ํ™” ๊ธฐ๋ก ์‹œ์ž‘ ๋ถ€๋ถ„์— ์ปจํ…์ŠคํŠธ ์‚ฝ์ž…
body.setdefault("messages", []).insert(0, context_message)
return body

๐Ÿ“– ๋ฌด์Šจ ์ผ์ด ์ผ์–ด๋‚˜๋‚˜์š”?

  • ์‚ฌ์šฉ์ž์˜ ์ž…๋ ฅ "์ €๋… ์‹์‚ฌ ์•„์ด๋””์–ด๊ฐ€ ๋ญ๊ฐ€ ์ข‹์•„์š”?"๋Š” ์ด์ œ ์ดํƒˆ๋ฆฌ์•„ ํ…Œ๋งˆ๋ฅผ ๋ฐ˜์˜ํ•ฉ๋‹ˆ๋‹ค. ์‹œ์Šคํ…œ ์ปจํ…์ŠคํŠธ๋ฅผ ์„ค์ •ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์น˜์ฆˆ ์ผ€์ดํฌ๋Š” ๋‹ต๋ณ€์— ๋“ฑ์žฅํ•˜์ง€ ์•Š์„ ๊ฐ€๋Šฅ์„ฑ์ด ๋†’์ง€๋งŒ, ํŒŒ์Šคํƒ€๋Š” ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.
๐Ÿ”ช ์˜ˆ์ œ 2: ์ž…๋ ฅ ์ •ํ™” (์ด์ƒํ•œ ๋ฌธ์ž ์ œ๊ฑฐ)โ€‹

์‚ฌ์šฉ์ž ์ž…๋ ฅ์ด ์ง€์ €๋ถ„ํ•˜๊ฑฐ๋‚˜ !!!์™€ ๊ฐ™์€ ๋ถˆํ•„์š”ํ•œ ๊ธฐํ˜ธ๋ฅผ ํฌํ•จํ•˜์—ฌ ๋ชจ๋ธ์ด ๋Œ€ํ™”๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์–ด๋ ต๊ฒŒ ๋งŒ๋“œ๋Š” ๊ฒฝ์šฐ, ํ•ต์‹ฌ ๋‚ด์šฉ์„ ๋ณด์กดํ•˜๋ฉด์„œ ์ด๋ฅผ ์ •๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

def inlet(self, body: dict, __user__: Optional[dict] = None) -> dict:
# ๋งˆ์ง€๋ง‰ ์‚ฌ์šฉ์ž ์ž…๋ ฅ ์ •ํ™” (๋ฉ”์‹œ์ง€ ๋ชฉ๋ก ๋์—์„œ ๊ฐ€์ ธ์˜ค๊ธฐ)
last_message = body["messages"][-1]["content"]
body["messages"][-1]["content"] = last_message.replace("!!!", "").strip()
return body

๐Ÿ“– ๋ฌด์Šจ ์ผ์ด ์ผ์–ด๋‚˜๋‚˜์š”?

  • ์ด์ „: "์ด ๋ฌธ์ œ๋ฅผ ์–ด๋–ป๊ฒŒ ๋””๋ฒ„๊น…ํ•˜์ฃ !!!" โžก๏ธ ๋ชจ๋ธ๋กœ ์ „์†ก๋จ: "์ด ๋ฌธ์ œ๋ฅผ ์–ด๋–ป๊ฒŒ ๋””๋ฒ„๊น…ํ•˜์ฃ "

์ฐธ๊ณ : ์‚ฌ์šฉ์ž๋Š” ๊ฐ™์€ ๋А๋‚Œ์„ ๋ฐ›์ง€๋งŒ, ๋ชจ๋ธ์€ ๋” ๊น”๋”ํ•˜๊ณ  ์ดํ•ดํ•˜๊ธฐ ์‰ฌ์šด ์ฟผ๋ฆฌ๋ฅผ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ“Š LLM์— ์ž…๋ ฅ ์ตœ์ ํ™”๋ฅผ ๋•๋Š” inlet:โ€‹
  • ๋ชจํ˜ธํ•œ ์งˆ๋ฌธ์„ ๋ช…ํ™•ํžˆ ํ•˜์—ฌ ์ •ํ™•๋„๋ฅผ ํ–ฅ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค.
  • ๋ถˆํ•„์š”ํ•œ ๋…ธ์ด์ฆˆ(์ด๋ชจ์ง€, HTML ํƒœ๊ทธ, ์ถ”๊ฐ€ ๊ตฌ๋‘์  ๋“ฑ)๋ฅผ ์ œ๊ฑฐํ•˜์—ฌ AI์˜ ํšจ์œจ์„ฑ์„ ๋†’์ž…๋‹ˆ๋‹ค.
  • ์‚ฌ์šฉ์ž์˜ ์ž…๋ ฅ์„ ๋ชจ๋ธ์ด ์˜ˆ์ƒํ•˜๋Š” ํŒจํ„ด ๋˜๋Š” ์Šคํ‚ค๋งˆ์™€ ์ผ์น˜ํ•˜๋„๋ก ํฌ๋งทํŒ…ํ•˜์—ฌ ์ผ๊ด€์„ฑ์„ ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค. (์˜ˆ: ํŠน์ • ์šฉ๋„์— ๋งž์ถ˜ JSON ํ˜•์‹ ๋“ฑ)

๐Ÿ’ญ inlet์„ ์ฃผ๋ฐฉ์˜ ๋ณด์กฐ ์…ฐํ”„๋กœ ์ƒ๊ฐํ•˜์„ธ์š”โ€”๋ชจ๋ธ(๊ท€ํ•˜์˜ AI '๋ ˆ์‹œํ”ผ')์— ์ž…๋ ฅ๋˜๋Š” ๋ชจ๋“  ๋ฐ์ดํ„ฐ๊ฐ€ ์™„๋ฒฝํžˆ ์ค€๋น„๋˜๊ณ , ์„ธ์ฒ™๋˜๊ณ , ์–‘๋…๋œ ์ƒํƒœ๋กœ ๋“ค์–ด์˜ค๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. ์ž…๋ ฅ์ด ์ข‹์œผ๋ฉด ์ถœ๋ ฅ๋„ ์ข‹์•„์ง‘๋‹ˆ๋‹ค!


๐Ÿ†• 3๏ธโƒฃ stream ํ›… (Open WebUI 0.5.17์˜ ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ)โ€‹

๐Ÿ”„ stream ํ›…์ด๋ž€?โ€‹

stream ํ•จ์ˆ˜๋Š” Open WebUI 0.5.17์—์„œ ์ƒˆ๋กญ๊ฒŒ ๋„์ž…๋œ ๊ธฐ๋Šฅ์œผ๋กœ, ๋ชจ๋ธ์˜ ์ŠคํŠธ๋ฆฌ๋ฐ ์‘๋‹ต์„ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๊ฐ€๋กœ์ฑ„๊ณ  ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.

outlet์ด ์™„์ „ํ•œ ์‘๋‹ต์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ๊ณผ ๋‹ฌ๋ฆฌ, stream์€ ๋ชจ๋ธ์—์„œ ์ˆ˜์‹ ๋œ ๊ฐœ๋ณ„ ์ฒญํฌ๋ณ„๋กœ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ› ๏ธ Stream Hook์„ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ์ƒํ™ฉโ€‹
  • ์‚ฌ์šฉ์ž์—๊ฒŒ ํ‘œ์‹œ๋˜๊ธฐ ์ „, ์ŠคํŠธ๋ฆฌ๋ฐ ์‘๋‹ต์„ ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค.
  • ์‹ค์‹œ๊ฐ„ ๊ฒ€์—ด ๋˜๋Š” ์ •๋ฆฌ๋ฅผ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.
  • ์ŠคํŠธ๋ฆฌ๋ฐ ๋ฐ์ดํ„ฐ๋ฅผ ๋ชจ๋‹ˆํ„ฐ๋งํ•˜๋ฉฐ ๋กœ๊น…/๋””๋ฒ„๊น…ํ•ฉ๋‹ˆ๋‹ค.
๐Ÿ“œ ์˜ˆ์‹œ: ์ŠคํŠธ๋ฆฌ๋ฐ ์ฒญํฌ ๋กœ๊น…ํ•˜๊ธฐโ€‹

LLM์˜ ์ŠคํŠธ๋ฆฌ๋ฐ ์‘๋‹ต์„ ๊ฒ€์‚ฌํ•˜๊ณ  ์ˆ˜์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:

def stream(self, event: dict) -> dict:
print(event) # ๋“ค์–ด์˜ค๋Š” ๊ฐ ์ฒญํฌ๋ฅผ ๊ฒ€์‚ฌ์šฉ์œผ๋กœ ์ถœ๋ ฅ
return event

์ŠคํŠธ๋ฆฌ๋ฐ ์ด๋ฒคํŠธ ์˜ˆ์‹œ:

{"id": "chatcmpl-B4l99MMaP3QLGU5uV7BaBM0eDS0jb","choices": [{"delta": {"content": "Hi"}}]}
{"id": "chatcmpl-B4l99MMaP3QLGU5uV7BaBM0eDS0jb","choices": [{"delta": {"content": "!"}}]}
{"id": "chatcmpl-B4l99MMaP3QLGU5uV7BaBM0eDS0jb","choices": [{"delta": {"content": " ๐Ÿ˜Š"}}]}

๐Ÿ“– ๋ฌด์Šจ ์ผ์ด ๋ฒŒ์–ด์ง€๋‚˜์š”?

  • ๊ฐ ํ–‰์€ ๋ชจ๋ธ์˜ ์ŠคํŠธ๋ฆฌ๋ฐ ์‘๋‹ต์—์„œ ์ƒ์„ฑ๋œ ์ž‘์€ ์กฐ๊ฐ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.
  • delta.content ํ•„๋“œ์— ์ ์ง„์ ์œผ๋กœ ์ƒ์„ฑ๋œ ํ…์ŠคํŠธ๊ฐ€ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.
๐Ÿ”„ ์˜ˆ์‹œ: ์ŠคํŠธ๋ฆฌ๋ฐ ๋ฐ์ดํ„ฐ์—์„œ ์ด๋ชจ์ง€ ์ œ๊ฑฐโ€‹
def stream(self, event: dict) -> dict:
for choice in event.get("choices", []):
delta = choice.get("delta", {})
if "content" in delta:
delta["content"] = delta["content"].replace("๐Ÿ˜Š", "") # ์ด๋ชจ์ง€ ์ œ๊ฑฐ
return event

๐Ÿ“– Before: "Hi ๐Ÿ˜Š"
๐Ÿ“– After: "Hi"


4๏ธโƒฃ outlet ํ•จ์ˆ˜ (์ถœ๋ ฅ ํ›„์ฒ˜๋ฆฌ)โ€‹

outlet ํ•จ์ˆ˜๋Š” ๊ต์ •์ž์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค: AI์˜ ์‘๋‹ต์„ ๊น”๋”ํ•˜๊ฒŒ ์ •๋ฆฌํ•˜๊ฑฐ๋‚˜ LLM์—์„œ ์ฒ˜๋ฆฌ๋œ ํ›„ ์ตœ์ข… ๋ณ€๊ฒฝ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ“ค ์ž…๋ ฅ:

  • body: ์ฑ„ํŒ…์—์„œ ํ˜„์žฌ ๋ชจ๋“  ๋ฉ”์‹œ์ง€(์‚ฌ์šฉ์ž ํžˆ์Šคํ† ๋ฆฌ + LLM ์‘๋‹ต)๊ฐ€ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.

๐Ÿš€ ๋‹น์‹ ์˜ ์ž‘์—…: ์ด body๋ฅผ ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค. ์ •๋ฆฌ, ์ถ”๊ฐ€ ๋˜๋Š” ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ๊ธฐ๋กํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๊ฐ ์กฐ์ •์ด ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์— ๋ฏธ์น˜๋Š” ์˜ํ–ฅ์„ ์—ผ๋‘์— ๋‘์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ’ก ์ตœ๊ณ ์˜ ๊ด€ํ–‰:

  • outlet์—์„œ ์ง์ ‘ ํŽธ์ง‘ํ•˜๊ธฐ๋ณด๋‹ค ๋กœ๊น…์„ ์„ ํ˜ธํ•˜์„ธ์š” (์˜ˆ: ๋””๋ฒ„๊น… ๋˜๋Š” ๋ถ„์„์šฉ).
  • ์ถœ๋ ฅ ํ˜•์‹์— ํฐ ์ˆ˜์ •์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ pipe ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ๊ณ ๋ คํ•˜์„ธ์š”.

๐Ÿ’ก ์˜ˆ์‹œ ํ™œ์šฉ ์‚ฌ๋ก€: ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ณด์—ฌ์ฃผ๊ณ  ์‹ถ์ง€ ์•Š์€ ๋ฏผ๊ฐํ•œ API ์‘๋‹ต ์ œ๊ฑฐ:

def outlet(self, body: dict, __user__: Optional[dict] = None) -> dict:
for message in body["messages"]:
message["content"] = message["content"].replace("<API_KEY>", "[REDACTED]")
return body

๐ŸŒŸ ํ•„ํ„ฐ ํ™œ์šฉ: ์‹ค์šฉ์ ์ธ ์˜ˆ์ œ ๋งŒ๋“ค๊ธฐโ€‹

ํ•„ํ„ฐ๋ฅผ ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ•˜๋Š”์ง€ ์‹ค์งˆ์ ์ธ ์˜ˆ์ œ๋ฅผ ํ†ตํ•ด ์•Œ์•„๋ด…์‹œ๋‹ค!

๐Ÿ“š ์˜ˆ์‹œ #1: ์‚ฌ์šฉ์ž ์ž…๋ ฅ์— ํ•ญ์ƒ ์ปจํ…์ŠคํŠธ ์ถ”๊ฐ€โ€‹

LLM์ด ๊ณ ๊ฐ์ด ์†Œํ”„ํŠธ์›จ์–ด ๋ฒ„๊ทธ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐ ๋„์›€์„ ์ฃผ๊ณ  ์žˆ๋‹ค๋Š” ์‚ฌ์‹ค์„ ํ•ญ์ƒ ์ธ์ง€ํ•˜๋„๋ก ํ•˜๊ณ  ์‹ถ์œผ์‹ ๊ฐ€์š”? **"๋‹น์‹ ์€ ์†Œํ”„ํŠธ์›จ์–ด ๋ฌธ์ œ ํ•ด๊ฒฐ ์–ด์‹œ์Šคํ„ดํŠธ์ž…๋‹ˆ๋‹ค"**์™€ ๊ฐ™์€ ์ง€์นจ์„ ๊ฐ ์‚ฌ์šฉ์ž ์งˆ๋ฌธ์— ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

class Filter:
def inlet(self, body: dict, __user__: Optional[dict] = None) -> dict:
context_message = {
"role": "system",
"content": "Youre a software troubleshooting assistant."
}
body.setdefault("messages", []).insert(0, context_message)
return body

๐Ÿ“š ์˜ˆ์‹œ #2: ์ฝ๊ธฐ ์‰ฝ๊ฒŒ ์ถœ๋ ฅ ํ•˜์ด๋ผ์ดํŠธํ•˜๊ธฐโ€‹

Markdown ๋˜๋Š” ๋‹ค๋ฅธ ์„œ์‹ ์Šคํƒ€์ผ๋กœ ์ถœ๋ ฅ์„ ๋ฐ˜ํ™˜ํ•˜๊ณ  ์‹ถ์œผ์‹ ๊ฐ€์š”? outlet ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”!

class Filter:
def outlet(self, body: dict, __user__: Optional[dict] = None) -> dict:
# ๊ฐ ์‘๋‹ต์— 'ํ•˜์ด๋ผ์ดํŠธ' ๋งˆํฌ๋‹ค์šด ์ถ”๊ฐ€
for message in body["messages"]:
if message["role"] == "assistant": # ๋ชจ๋ธ ์‘๋‹ต ํƒ€๊ฒŸํŒ…
message["content"] = f"**{message[content]}**" # ๋งˆํฌ๋‹ค์šด์œผ๋กœ ๊ฐ•์กฐ
return body

๐Ÿšง ์ž ์žฌ์  ํ˜ผ๋ž€: FAQ ๋ช…ํ™•ํžˆ ํ•˜๊ธฐ ๐Ÿ›‘โ€‹

Q: ํ•„ํ„ฐ๊ฐ€ ํŒŒ์ดํ”„ ํ•จ์ˆ˜์™€ ์–ด๋–ป๊ฒŒ ๋‹ค๋ฅธ๊ฐ€์š”?โ€‹

ํ•„ํ„ฐ๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ๋ชจ๋ธ๋กœ ๊ฐ€๊ฑฐ๋‚˜ ๋ชจ๋ธ์—์„œ ์˜ค๋Š” ๊ณผ์ •์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์ •ํ•˜์ง€๋งŒ, ์ด ๋‹จ๊ณ„๋“ค ๋ฐ”๊นฅ์—์„œ ๋กœ์ง๊ณผ ํฌ๊ฒŒ ์ƒํ˜ธ์ž‘์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋ฐ˜๋ฉด, ํŒŒ์ดํ”„๋Š”:

  • ์™ธ๋ถ€ API๋ฅผ ํ†ตํ•ฉํ•˜๊ฑฐ๋‚˜ ๋ฐฑ์—”๋“œ๊ฐ€ ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ์‹์„ ํฌ๊ฒŒ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์™„์ „ํžˆ ์ƒˆ๋กœ์šด "๋ชจ๋ธ"๋กœ ์‚ฌ์šฉ์ž ์ •์˜ ๋กœ์ง์„ ๋…ธ์ถœํ•ฉ๋‹ˆ๋‹ค.

Q: outlet ๋‚ด์—์„œ ๋Œ€๊ทœ๋ชจ ํ›„์ฒ˜๋ฆฌ๋ฅผ ํ•  ์ˆ˜ ์žˆ๋‚˜์š”?โ€‹

ํ•  ์ˆ˜๋Š” ์žˆ์ง€๋งŒ, ์ตœ์„ ์˜ ๋ฐฉ๋ฒ•์€ ์•„๋‹™๋‹ˆ๋‹ค.:

  • ํ•„ํ„ฐ๋Š” ๊ฐ€๋ฒผ์šด ๋ณ€๊ฒฝ์„ ๊ฐ€ํ•˜๊ฑฐ๋‚˜ ๋กœ๊น…์— ์ ํ•ฉํ•˜๊ฒŒ ์„ค๊ณ„๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
  • ๋Œ€๊ทœ๋ชจ ์ˆ˜์ •์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ ๋Œ€์‹  ํŒŒ์ดํ”„ ํ•จ์ˆ˜๋ฅผ ๊ณ ๋ คํ•˜์„ธ์š”.

๐ŸŽ‰ ์š”์•ฝ: ์™œ ํ•„ํ„ฐ ํ•จ์ˆ˜๋ฅผ ์ž‘์„ฑํ•ด์•ผ ํ• ๊นŒ์š”?โ€‹

์ง€๊ธˆ๊นŒ์ง€ ์—ฌ๋Ÿฌ๋ถ„์€ ๋‹ค์Œ์„ ๋ฐฐ์› ์Šต๋‹ˆ๋‹ค:

  1. Inlet์€ ์‚ฌ์šฉ์ž ์ž…๋ ฅ์„ ์กฐ์ž‘ํ•ฉ๋‹ˆ๋‹ค (์‚ฌ์ „ ์ฒ˜๋ฆฌ).
  2. Stream์€ ์ŠคํŠธ๋ฆฌ๋ฐ ๋ชจ๋ธ ์ถœ๋ ฅ์„ ๊ฐ€๋กœ์ฑ„๊ณ  ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค (์‹ค์‹œ๊ฐ„).
  3. Outlet์€ AI ์ถœ๋ ฅ์„ ์กฐ์ •ํ•ฉ๋‹ˆ๋‹ค (์‚ฌํ›„ ์ฒ˜๋ฆฌ).
  4. ํ•„ํ„ฐ๋Š” ๋ฐ์ดํ„ฐ ํ๋ฆ„์— ๊ฐ€๋ฒผ์šด ์‹ค์‹œ๊ฐ„ ๋ณ€๊ฒฝ์„ ๊ฐ€ํ•˜๋Š” ๋ฐ ๊ฐ€์žฅ ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค.
  5. Valves๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํ•„ํ„ฐ๋ฅผ ๋™์ ์œผ๋กœ ๊ตฌ์„ฑํ•˜์—ฌ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋งž์ถคํ˜• ๋™์ž‘์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

๐Ÿš€ ์ด์ œ ๋‹น์‹  ์ฐจ๋ก€์ž…๋‹ˆ๋‹ค: ์–ด๋–ค ์ž‘์€ ์กฐ์ •์ด๋‚˜ ์ปจํ…์ŠคํŠธ ์ถ”๊ฐ€๊ฐ€ Open WebUI ๊ฒฝํ—˜์„ ํ–ฅ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ์„๊นŒ์š”? ํ•„ํ„ฐ๋Š” ๋งŒ๋“ค๊ธฐ ์žฌ๋ฏธ์žˆ๊ณ  ์‚ฌ์šฉ์ด ์œ ์—ฐํ•˜๋ฉฐ, ์—ฌ๋Ÿฌ๋ถ„์˜ ๋ชจ๋ธ์„ ๋‹ค์Œ ๋‹จ๊ณ„๋กœ ๋Œ์–ด์˜ฌ๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค!

ํ–‰๋ณตํ•œ ์ฝ”๋”ฉ ๋˜์„ธ์š”! โœจ