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

๐Ÿ› ๏ธ ๊ฐœ๋ฐœ

์‚ฌ์šฉ์ž ์ •์˜ ๋„๊ตฌ ํ‚คํŠธ ์ž‘์„ฑโ€‹

๋„๊ตฌ ํ‚คํŠธ๋Š” ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ํฌํ•จํ•˜๋Š” ์ƒ๋‹จ ์ˆ˜์ค€์˜ docstring๊ณผ Tools ํด๋ž˜์Šค๊ฐ€ ํฌํ•จ๋œ ๋‹จ์ผ Python ํŒŒ์ผ์—์„œ ์ •์˜๋ฉ๋‹ˆ๋‹ค.

์ƒ๋‹จ ์ˆ˜์ค€ Docstring ์˜ˆโ€‹

"""
title: ๋ฌธ์ž์—ด ๋ฐ˜์ „
author: ์ž‘์„ฑ์ž ์ด๋ฆ„
author_url: https://website.com
git_url: https://github.com/username/string-reverse.git
description: ์ด ๋„๊ตฌ๋Š” ๋ฌธ์ž์—ด์˜ ๋ฐ˜์ „์„ ๊ณ„์‚ฐํ•ฉ๋‹ˆ๋‹ค
required_open_webui_version: 0.4.0
requirements: langchain-openai, langgraph, ollama, langchain_ollama
version: 0.4.0
licence: MIT
"""

๋„๊ตฌ ํด๋ž˜์Šคโ€‹

Tools๋ผ๋Š” ํด๋ž˜์Šค ๋‚ด ๋ฉ”์„œ๋“œ๋กœ ๋„๊ตฌ๋ฅผ ์ •์˜ํ•ด์•ผ ํ•˜๋ฉฐ, ์„ ํƒ์ ์œผ๋กœ Valves ๋ฐ UserValves๋ผ๋Š” ํ•˜์œ„ ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ:

class Tools:
def __init__(self):
"""๋„๊ตฌ๋ฅผ ์ดˆ๊ธฐํ™”ํ•ฉ๋‹ˆ๋‹ค."""
self.valves = self.Valves()

class Valves(BaseModel):
api_key: str = Field("", description="์—ฌ๊ธฐ์— API ํ‚ค๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”")

def reverse_string(self, string: str) -> str:
"""
์ž…๋ ฅ ๋ฌธ์ž์—ด์„ ๋ฐ˜์ „ํ•ฉ๋‹ˆ๋‹ค.
:param string: ๋ฐ˜์ „ํ•  ๋ฌธ์ž์—ด
"""
# ๋ฐธ๋ธŒ ์‚ฌ์šฉ ์˜ˆ
if self.valves.api_key != "42":
return "์ž˜๋ชป๋œ API ํ‚ค"
return string[::-1]

ํƒ€์ž… ํžŒํŠธโ€‹

๊ฐ ๋„๊ตฌ๋Š” ์ธ์ˆ˜์— ๋Œ€ํ•œ ํƒ€์ž… ํžŒํŠธ๋ฅผ ๊ฐ€์ ธ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํƒ€์ž…์€ queries_and_docs: list[tuple[str, int]]์ฒ˜๋Ÿผ ์ค‘์ฒฉ๋  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ํƒ€์ž… ํžŒํŠธ๋Š” ๋ชจ๋ธ์— ์ „๋‹ฌ๋˜๋Š” JSON ์Šคํ‚ค๋งˆ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ํƒ€์ž… ํžŒํŠธ๊ฐ€ ์—†๋Š” ๋„๊ตฌ๋Š” ์ผ๊ด€์„ฑ์ด ํฌ๊ฒŒ ๋–จ์–ด์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฐธ๋ธŒ(Valves) ๋ฐ ์‚ฌ์šฉ์ž ๋ฐธ๋ธŒ(UserValves) - (์„ ํƒ ์‚ฌํ•ญ, ํ•˜์ง€๋งŒ ๊ฐ•๋ ฅํžˆ ๊ถŒ์žฅ๋จ)โ€‹

๋ฐธ๋ธŒ(Valves)์™€ ์‚ฌ์šฉ์ž ๋ฐธ๋ธŒ(UserValves)๋Š” ๋„๊ตฌ์˜ ์„ค์ •์„ ์‚ฌ์šฉ์žํ™”ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ์ „์šฉ Valves & UserValves ํŽ˜์ด์ง€์—์„œ ์ž์„ธํžˆ ์ฝ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์„ ํƒ์  ์ธ์ˆ˜โ€‹

์•„๋ž˜๋Š” ๋„๊ตฌ๊ฐ€ ์˜์กดํ•  ์ˆ˜ ์žˆ๋Š” ์„ ํƒ์  ์ธ์ˆ˜ ๋ชฉ๋ก์ž…๋‹ˆ๋‹ค:

  • __event_emitter__: ์ด๋ฒคํŠธ ์ „์†ก (์•„๋ž˜ ์„น์…˜ ์ฐธ์กฐ)
  • __event_call__: ์ด๋ฒคํŠธ ์ „์†ก๊ณผ ๋™์ผํ•˜์ง€๋งŒ ์‚ฌ์šฉ์ž ์ƒํ˜ธ์ž‘์šฉ์— ์‚ฌ์šฉ
  • __user__: ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ํฌํ•จํ•˜๋Š” ๋”•์…”๋„ˆ๋ฆฌ. __user__["valves"]์— UserValves ๊ฐ์ฒด๋„ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.
  • __metadata__: ์ฑ„ํŒ… ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ๋”•์…”๋„ˆ๋ฆฌ
  • __messages__: ์ด์ „ ๋ฉ”์‹œ์ง€์˜ ๋ชฉ๋ก
  • __files__: ์ฒจ๋ถ€๋œ ํŒŒ์ผ
  • __model__: ๋ชจ๋ธ ์ •๋ณด๋ฅผ ํฌํ•จํ•˜๋Š” ๋”•์…”๋„ˆ๋ฆฌ

์œ„ ์ธ์ˆ˜๋ฅผ ๊ฐ ๋„๊ตฌ ํด๋ž˜์Šค์˜ ๋ฉ”์„œ๋“œ์— ์ถ”๊ฐ€ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. ์œ„์˜ ์˜ˆ์—์„œ __user__์ฒ˜๋Ÿผ ์ถ”๊ฐ€ํ•˜์‹ญ์‹œ์˜ค.

์ด๋ฒคํŠธ ๋ฐœ์ƒ๊ธฐโ€‹

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

์ด๋ฒคํŠธ ๋ฐœ์ƒ๊ธฐ์—๋Š” ๋‘ ๊ฐ€์ง€ ์œ ํ˜•์ด ์žˆ์Šต๋‹ˆ๋‹ค:

๋ชจ๋ธ์ด ๋„๊ตฌ๋ฅผ ํ˜ธ์ถœํ•  ์ˆ˜ ์—†๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ด๋ฉด, ๋„๊ตฌ๊ฐ€ ํ™œ์„ฑํ™”๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธํ•˜์„ธ์š”(๋ชจ๋ธ ํŽ˜์ด์ง€ ๋˜๋Š” ์ฑ„ํŒ… ์ž…๋ ฅ ํ•„๋“œ ์˜†์˜ + ๊ธฐํ˜ธ๋ฅผ ํ†ตํ•ด ํ™œ์„ฑํ™” ๊ฐ€๋Šฅ). ๋˜ํ•œ ๋ชจ๋ธ ํŽ˜์ด์ง€์˜ ๊ณ ๊ธ‰ ๋งค๊ฐœ๋ณ€์ˆ˜ ์„น์…˜์—์„œ Function Calling ์ธ์ˆ˜๋ฅผ Default์—์„œ Native๋กœ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ƒํƒœโ€‹

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

await __event_emitter__(
{
"type": "status", # ์—ฌ๊ธฐ์—์„œ ์œ ํ˜•์„ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค
"data": {"description": "์ฑ„ํŒ…์— ํ‘œ์‹œ๋˜๋Š” ๋ฉ”์‹œ์ง€", "done": False, "hidden": False},
# `done`์ด False์ž„์„ ์œ ์˜ํ•˜์„ธ์š”. ์ด๋Š” ์—ฌ์ „ํžˆ ์ƒํƒœ๋ฅผ ์ „์†กํ•˜๊ณ  ์žˆ์Œ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.
}
)
์˜ˆ์ œ
async def test_function(
self, prompt: str, __user__: dict, __event_emitter__=None
) -> str:
"""
์ด๊ฒƒ์€ ๋ฐ๋ชจ์ž…๋‹ˆ๋‹ค

:param test: ์ด๊ฒƒ์€ ํ…Œ์ŠคํŠธ ๋งค๊ฐœ๋ณ€์ˆ˜์ž…๋‹ˆ๋‹ค
"""

await __event_emitter__(
{
"type": "status", # ์—ฌ๊ธฐ์—์„œ ์œ ํ˜•์„ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค
"data": {"description": "์ฑ„ํŒ…์— ํ‘œ์‹œ๋˜๋Š” ๋ฉ”์‹œ์ง€", "done": False},
# `done`์ด False์ž„์„ ์œ ์˜ํ•˜์„ธ์š”. ์ด๋Š” ์—ฌ์ „ํžˆ ์ƒํƒœ๋ฅผ ์ „์†กํ•˜๊ณ  ์žˆ์Œ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.
}
)

# ์—ฌ๊ธฐ์—์„œ ๋‹ค๋ฅธ ๋กœ์ง์„ ์ˆ˜ํ–‰ํ•˜์‹ญ์‹œ์˜ค
await __event_emitter__(
{
"type": "status",
"data": {"description": "์ž‘์—… ๋ฉ”์‹œ์ง€ ์™„๋ฃŒ", "done": True, "hidden": False},
# `done`์ด True์ž„์„ ์œ ์˜ํ•˜์„ธ์š”. ์ด๋Š” ์ƒํƒœ ์ „์†ก์ด ์™„๋ฃŒ๋˜์—ˆ์Œ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.
# ๋ฉ”์‹œ์ง€๊ฐ€ ๋ฐ˜ํ™˜๋œ ํ›„ ์ƒํƒœ๋ฅผ ์ œ๊ฑฐํ•˜๋ ค๋ฉด "hidden": True๋กœ ์„ค์ •ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
}
)

except Exception as e:
await __event_emitter__(
{
"type": "status",
"data": {"description": f"์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค: {e}", "done": True},
}
)

return f"์‚ฌ์šฉ์ž์—๊ฒŒ ์•Œ๋ฆฌ๊ธฐ: {e}"

๋ฉ”์‹œ์ง€โ€‹

์ด ํƒ€์ž…์€ Tool์˜ ์–ด๋А ๋‹จ๊ณ„์—์„œ๋‚˜ LLM์— ๋ฉ”์‹œ์ง€๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ LLM ์‘๋‹ต ์ „, ํ›„, ๋„์ค‘์— ๋ฉ”์‹œ์ง€๋ฅผ ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜ ์ด๋ฏธ์ง€๋ฅผ ์‚ฝ์ž…ํ•˜๊ฑฐ๋‚˜ ์›น ํŽ˜์ด์ง€๋ฅผ ๋ Œ๋”๋งํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

await __event_emitter__(
{
"type": "message", # ์—ฌ๊ธฐ์„œ ํƒ€์ž…์„ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค
"data": {"content": "์ด ๋ฉ”์‹œ์ง€๋Š” ์ฑ„ํŒ…์— ์ถ”๊ฐ€๋ฉ๋‹ˆ๋‹ค."},
# ๋ฉ”์‹œ์ง€ ํƒ€์ž…์—์„œ๋Š” ์™„๋ฃŒ ์กฐ๊ฑด์„ ์„ค์ •ํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค
}
)
์˜ˆ์ œ
async def test_function(
self, prompt: str, __user__: dict, __event_emitter__=None
) -> str:
"""
์ด๊ฑด ๋ฐ๋ชจ์ž…๋‹ˆ๋‹ค

:param test: ์ด๊ฑด ํ…Œ์ŠคํŠธ ๋งค๊ฐœ๋ณ€์ˆ˜์ž…๋‹ˆ๋‹ค
"""

await __event_emitter__(
{
"type": "message", # ์—ฌ๊ธฐ์„œ ํƒ€์ž…์„ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค
"data": {"content": "์ด ๋ฉ”์‹œ์ง€๋Š” ์ฑ„ํŒ…์— ์ถ”๊ฐ€๋ฉ๋‹ˆ๋‹ค."},
# ๋ฉ”์‹œ์ง€ ํƒ€์ž…์—์„œ๋Š” ์™„๋ฃŒ ์กฐ๊ฑด์„ ์„ค์ •ํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค
}
)

except Exception as e:
await __event_emitter__(
{
"type": "status",
"data": {"description": f"์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค: {e}", "done": True},
}
)

return f"์‚ฌ์šฉ์ž์—๊ฒŒ ์•Œ๋ฆฌ๊ธฐ: {e}"

์ธ์šฉโ€‹

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

await __event_emitter__(
{
"type": "citation",
"data": {
"document": [content],
"metadata": [
{
"date_accessed": datetime.now().isoformat(),
"source": title,
}
],
"source": {"name": title, "url": url},
},
}
)

์—ฌ๋Ÿฌ ์ธ์šฉ์„ ๋ณด๋‚ด๋ ค๋ฉด ์ธ์šฉ์„ ๋ฐ˜๋ณต์ ์œผ๋กœ ๋‹ค๋ฃจ๊ณ  ์—๋ฏธํ„ฐ๋ฅผ ์—ฌ๋Ÿฌ ๋ฒˆ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž ์ •์˜ ์ธ์šฉ์„ ๊ตฌํ˜„ํ•  ๋•Œ, Tools ํด๋ž˜์Šค์˜ __init__ ๋ฉ”์„œ๋“œ์—์„œ self.citation = False๋ฅผ ์„ค์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ๋‚ด์žฅ๋œ ์ธ์šฉ์ด ๋ณด๋‚ธ ์ธ์šฉ์„ ๋ฎ์–ด์“ฐ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด:

def __init__(self):
self.citation = False

์ฃผ์˜: ๋งŒ์•ฝ self.citation = True๋ฅผ ์„ค์ •ํ•˜๋ฉด, ์ด๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ๋ณด๋‚ธ ์‚ฌ์šฉ์ž ์ •์˜ ์ธ์šฉ์„ ์ž๋™ ์ƒ์„ฑ๋œ ๋ฐ˜ํ™˜ ์ธ์šฉ์œผ๋กœ ๋Œ€์ฒดํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ๋น„ํ™œ์„ฑํ™”ํ•˜๋ฉด ์‚ฌ์šฉ์ž๊ฐ€ ์ž์‹ ์˜ ์ธ์šฉ ์ฐธ๊ณ ๋ฅผ ์™„์ „ํžˆ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ์ œ
class Tools:
class UserValves(BaseModel):
test: bool = Field(
default=True, description="ํ…Œ์ŠคํŠธ"
)

def __init__(self):
self.citation = False

async def test_function(
self, prompt: str, __user__: dict, __event_emitter__=None
) -> str:
"""
์ด๊ฑด ๋‹จ์ˆœํžˆ ์ธ์šฉ์„ ์ƒ์„ฑํ•˜๋Š” ๋ฐ๋ชจ์ž…๋‹ˆ๋‹ค

:param test: ์ด๊ฑด ํ…Œ์ŠคํŠธ ๋งค๊ฐœ๋ณ€์ˆ˜์ž…๋‹ˆ๋‹ค
"""

await __event_emitter__(
{
"type": "citation",
"data": {
"document": ["์ด ๋ฉ”์‹œ์ง€๋Š” ํด๋ฆญ ์‹œ ์ฑ„ํŒ…์˜ ์ธ์šฉ์œผ๋กœ ์ถ”๊ฐ€๋ฉ๋‹ˆ๋‹ค"],
"metadata": [
{
"date_accessed": datetime.now().isoformat(),
"source": title,
}
],
"source": {"name": "์ปจํ…์ธ  ์ œ๋ชฉ", "url": "http://link-to-citation"},
},
}
)

์™ธ๋ถ€ ํŒจํ‚ค์ง€โ€‹

Tools ์ •์˜ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ์—์„œ ์‚ฌ์šฉ์ž ์ •์˜ ํŒจํ‚ค์ง€๋ฅผ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ €์žฅ์„ ํด๋ฆญํ•˜๋ฉด ์ค„์ด ๋ถ„์„๋˜๊ณ  pip install์ด ๋ชจ๋“  ์š”๊ตฌ ์‚ฌํ•ญ์— ๋Œ€ํ•ด ํ•œ ๋ฒˆ์— ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

pip์ด Open WebUI์™€ ๋™์ผํ•œ ํ”„๋กœ์„ธ์Šค์—์„œ ์‚ฌ์šฉ๋˜๋ฏ€๋กœ ์„ค์น˜ ์ค‘์— UI๊ฐ€ ์™„์ „ํžˆ ๋ฐ˜์‘ํ•˜์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

Open WebUI์˜ ์š”๊ตฌ ์‚ฌํ•ญ๊ณผ์˜ ํŒจํ‚ค์ง€ ์ถฉ๋Œ์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ์กฐ์น˜๋Š” ์ทจํ•ด์ง€์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ฆ‰, ์š”๊ตฌ ์‚ฌํ•ญ์„ ์ง€์ •ํ•˜๋ฉด ์ฃผ์˜ํ•˜์ง€ ์•Š์„ ๊ฒฝ์šฐ Open WebUI๊ฐ€ ์†์ƒ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด open-webui ์ž์ฒด๋ฅผ ์š”๊ตฌ ์‚ฌํ•ญ์œผ๋กœ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ์ œ
"""
title: myToolName
author: myName
funding_url: [์—ฌ๊ธฐ์— ๋งํฌ๋ฅผ ์ž…๋ ฅํ•˜๋ฉด ์‚ฌ์šฉ์ž๊ฐ€ `ํ•˜ํŠธ` ๋ฒ„ํŠผ ๋’ค์— ํ‘œ์‹œ๋œ ๋งํฌ๋ฅผ ํ†ตํ•ด ์ง€์›์„ ๋ณด์—ฌ์ค„ ๊ฒƒ์ž…๋‹ˆ๋‹ค]
version: 1.0.0
# ๋ฒ„์ „์€ UI์— ํ‘œ์‹œ๋˜์–ด ์‚ฌ์šฉ์ž๊ฐ€ ์—…๋ฐ์ดํŠธ๋ฅผ ์ถ”์ ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ค๋‹ˆ๋‹ค.
license: GPLv3
description: [๊ถŒ์žฅ๋จ]
requirements: package1>=2.7.0,package2,package3
"""