
giskard-oss giskard-checks/v1.0.4
๐ข LLM ์์ด์ ํธ์ฉ ์คํ์์ค ํ๊ฐ ๋ฐ ํ ์คํธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ
์์ด์ ํธ ์์คํ ์ ์ํ ํ๊ฐ(Evals), ๋ ๋ ํ(Red Teaming) ๋ฐ ํ ์คํธ ์์ฑ
๋ชจ๋ํ, ๊ฒฝ๋, ๋์ ๋ฐ Async ์ฐ์
๋ฌธ์ โข ์น์ฌ์ดํธ โข ์ปค๋ฎค๋ํฐ
[!IMPORTANT] Giskard v3๋ AI ์์ด์ ํธ์ ๋์ ๋ค์ค ํด ํ ์คํธ๋ฅผ ์ํด ์๋กญ๊ฒ ์ฌ์์ฑ๋ ๋ฒ์ ์ ๋๋ค. ์ด๋ฒ ๋ฆด๋ฆฌ์ค๋ ํจ์จ์ฑ์ ๋์ด๊ธฐ ์ํด ๋ฌด๊ฑฐ์ด ์์กด์ฑ์ ์ ๊ฑฐํ๋ฉด์, ๋ ๊ฐ๋ ฅํ AI ์ทจ์ฝ์ ์ค์บ๋์ ํฅ์๋ RAG ํ๊ฐ๋ฅผ ๋์ ํ์ต๋๋ค. ๋ ๊ธฐ๋ฅ ๋ชจ๋ ์ด์
giskard-scan์ ๊ธฐ๋ณธ ๋ด์ฅ๋์ด v2์ ๋ํ ์์กด์ฑ์ด ์์ต๋๋ค. ํ ์ด๋ธ ํ์/ML ๋ชจ๋ธ์ ์ํ ๋ ๊ฑฐ์ ์ค์บ๋ง v2 ์ ์ฉ์ผ๋ก ์ ์ง๋ฉ๋๋ค. Giskard v2๋ ๊ณ์ ์ฌ์ฉํ ์ ์์ง๋ง ๋ ์ด์ ์ ๊ทน์ ์ผ๋ก ์ ์ง๋ณด์๋์ง ์์ต๋๋ค. ์งํ ์ํฉ์ ํ๋ก์ฐํ์ธ์ โ v3 ๋ฐํ ์ฝ๊ธฐ ยท ๋ก๋๋งต
์ค์น
pip install giskard # checks (+ agents, llm, core)
pip install "giskard[scan]" # + ์ทจ์ฝ์ / ํ์ง ์ค์บ
pip install "giskard[openai]" # LLM ํ์ /์์ฑ๊ธฐ๋ฅผ ์ํ provider SDK
Python 3.12+ ํ์.
| Extra | ์ถ๊ฐ ํญ๋ชฉ |
|---|---|
| (์์) | giskard-checks ๋ฐ ์์กด์ฑ |
scan | giskard-scan |
openai / anthropic / โฆ | provider SDK (pyproject.toml ์ ํ ์์กด์ฑ ์ฐธ์กฐ) |
ํ
๋ ๋ฉํธ๋ฆฌ: giskard-core๋ฅผ ํตํ ์ ํ์ ์ง๊ณ ๋ถ์. ํ๋กฌํํธ๋ ์ถ๋ ฅ์ ์ ์ก๋์ง ์์ต๋๋ค.
Giskard๋ฅผ importํ๊ธฐ ์ ์ ๋นํ์ฑํ: export DO_NOT_TRACK=1 ๋๋ export GISKARD_TELEMETRY_DISABLED=1.
์์ธํ ๋ด์ฉ: giskard-core README.
Giskard๋ ์์ด์ ํธ ์์คํ ์ ํ ์คํธํ๊ณ ํ๊ฐํ๊ธฐ ์ํ ์คํ์์ค Python ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋๋ค. v3 ์ํคํ ์ฒ๋ ๊ฐ๊ฐ ํ์ํ ์์กด์ฑ๋ง์ ํฌํจํ๋ ๋ชจ๋ํ์ ์ง์ค๋ ํจํค์ง ์ธํธ๋ก, LLM, ๋ธ๋๋ฐ์ค ์์ด์ ํธ ๋๋ ๋ค๋จ๊ณ ํ์ดํ๋ผ์ธ ๋ฑ ๋ฌด์์ด๋ ๋ํํ ์ ์๋๋ก ์ฒ์๋ถํฐ ๊ตฌ์ถ๋์์ต๋๋ค.
| ์ํ | ํจํค์ง | ์ค๋ช |
|---|---|---|
| โ ์์ | giskard-checks | ํ ์คํธ ๋ฐ ํ๊ฐ โ ์๋๋ฆฌ์ค API, ๋ด์ฅ ๊ฒ์ฌ, LLM-as-judge |
| โ ์์ | giskard-scan | ์์ด์ ํธ ์ทจ์ฝ์ ์ค์บ๋ + RAG/ํ์ง ํ๊ฐ โ ๋ ๋ ํ, ํ๋กฌํํธ ์ธ์ ์
, ํ์ฅ(jailbreaks) ๋ฐ ์ ํด ์ฝํ
์ธ (vulnerability_scan, v2 Scan์ ํ์), ์ง์ ๋ฒ ์ด์ค ํ์ง ํ๊ฐ (quality_scan, v2 RAGET์ ํ์) |
์ด๋ค์ ์ธ ๊ฐ์ง ๊ธฐ๋ฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ โ giskard-core(๊ณต์ฉ ์ ํธ๋ฆฌํฐ ๋ฐ ํ
๋ ๋ฉํธ๋ฆฌ), giskard-llm(provider์ ๊ตฌ์ ๋ฐ์ง ์๋ LLM ๋ผ์ฐํ
), giskard-agents(์์ด์ ํธ ๋ฐ ์ํฌํ๋ก์ฐ ์ค์ผ์คํธ๋ ์ด์
) โ ์์ ๊ตฌ์ถ๋๋ฉฐ, ์๋์ผ๋ก ์ค์น๋๋ฉฐ ์ง์ ์ฌ์ฉ๋๋ ๊ฒฝ์ฐ๋ ๋๋ญ
๋๋ค.
Giskard Checks โ ์์ด์ ํธ ํ ์คํธ๋ฅผ ์ํ ํ๊ฐ ์์ฑ ๋ฐ ์ ์ฉ
pip install giskard-checks
Giskard Checks ๋ LLM ๊ธฐ๋ฐ ์์คํ ์ ํ ์คํธํ๋ ํ๊ฐ(evals)๋ฅผ ์์ฑํ๊ธฐ ์ํ ๊ฒฝ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋๋ค. ๋จ์ํ ๋จ์ธ(assertion)๋ถํฐ LLM-as-judge ํ๊ฐ๊น์ง ํฌํจํฉ๋๋ค. ๊ธฐ์กด์ ๋จ์ ํ ์คํธ์ ๋ฌ๋ฆฌ, ํ๊ฐ๋ ๋น๊ฒฐ์ ์ ์ถ๋ ฅ์ ์ํด ์ค๊ณ๋์์ต๋๋ค. ๋์ผํ ์ ๋ ฅ์ด ์๋ก ๋ค๋ฅธ ์ ํจํ ์๋ต์ ์์ฑํ ์ ์๊ธฐ ๋๋ฌธ์ ๋๋ค.
Giskard Checks๋ฅผ ์ฌ์ฉํ์ฌ ๋ค์์ ์ํํ ์ ์์ต๋๋ค:
- ํ๊ท(regression) ๊ฐ์ง โ ๋ณ๊ฒฝ ํ์๋ ์์คํ ์ด ์ฌ๋ฐ๋ฅด๊ฒ ๋์ํ๋์ง ํ์ธ
- RAG ํ์ง ๊ฒ์ฆ โ ๋ต๋ณ์ด ๊ฒ์๋ ์ปจํ ์คํธ์ ๊ทผ๊ฑฐํ๋์ง ํ์ธ
- ์์ ๊ท์น ์ ์ฉ โ ์ถ๋ ฅ์ด ์ฝํ ์ธ ์ ์ฑ ์ ์ค์ํ๋์ง ํ์ธ
- ๋ค์ค ํด ์์ด์ ํธ ํ๊ฐ โ ๋จ์ผ ๊ตํ์ด ์๋ ์ ์ฒด ๋ํ ํ ์คํธ
๋ด์ฅ ํ๊ฐ์๋ ๋ฌธ์์ด ๋งค์นญ, ๋น๊ต, ์ ๊ท์, ์๋ฏธ๋ก ์ ์ ์ฌ์ฑ ๋ฐ LLM-as-judge ๊ฒ์ฌ(Groundedness, Conformity, LLMJudge)๊ฐ ํฌํจ๋ฉ๋๋ค.
๊ฐ๋
- Target โ ํ
์คํธ ๋์ ์์คํ
: ๋ชจ๋ ๋๊ธฐ/๋น๋๊ธฐ ํธ์ถ ๊ฐ๋ฅ ๊ฐ์ฒด
(inputs) -> outputs(์ ํ์ ์ผ๋กtraceํฌํจ) - Scenario โ ํ๋์ ํ๊ฐ: ์ํธ์์ฉ + ๊ฒ์ฌ
- Check โ ํธ๋ ์ด์ค์ ๋ํ ๋จ์ธ ๋๋ LLM ํ์
- Suite โ ํจ๊ป ์คํ๋๋ ์ฌ๋ฌ ์๋๋ฆฌ์ค
giskard.agents.Generator๋ ์ํฌํ๋ก์ฐ/ํ์ ์ ์ํ LLM ํด๋ผ์ด์ธํธ์
๋๋ค. ์ฌ์ฉ์ ๋ฉ์์ง๋ฅผ ํฉ์ฑํ๋
giskard.checks ์
๋ ฅ ์์ฑ๊ธฐ(LLMGenerator)์๋ ๋ค๋ฆ
๋๋ค.
๋น ๋ฅธ ์์
import asyncio
from giskard.checks import Scenario, Groundedness
def get_answer(inputs: str) -> str:
return "Paris" # ๋ชจ๋ธ / ์์ด์ ํธ๋ก ๊ต์ฒด
async def main() -> None:
scenario = (
Scenario("test_france_capital")
.interact(inputs="What is the capital of France?", outputs=get_answer)
.check(
Groundedness(
name="answer is grounded",
context="France is in Western Europe. Its capital is Paris.",
)
)
)
result = await scenario.run()
result.print_report()
asyncio.run(main())
Groundedness๋ LLM ํ์ ์
๋๋ค. provider extra(์: pip install "giskard[openai]")๋ฅผ ์ค์นํ๊ณ ํด๋น API ํค๋ฅผ ์ค์ ํ์ธ์. ๊ธฐ๋ณธ ๋ชจ๋ธ: openai/gpt-4o-mini.
Suites, LLMJudge, ๋ค์ค ํด ์๋๋ฆฌ์ค ๋ฑ์ ๋ํ ์์ธํ ๋ด์ฉ์ ์ ์ฒด ๋ฌธ์๋ฅผ ์ฐธ์กฐํ์ธ์.
Giskard Scan โ AI ์์ด์ ํธ์ฉ ์ทจ์ฝ์ ์ค์บ๋
pip install "giskard[scan]" # ๋๋: pip install giskard-scan
Giskard Scan์ ์์ด์ ํธ ์์คํ ์ ์ํ ๋ ๋ ํ ๋ฐ ์ทจ์ฝ์ ์ค์บ๋ ๊ณ์ธต์ ๋๋ค. ์์ด์ ํธ์ ๋ํ ์ผ๋ฐ ์ธ์ด ์ค๋ช ์์ ์ ๋์ ํ ์คํธ ์ค์ํธ๋ฅผ ์๋์ผ๋ก ์์ฑํ๋ฉฐ, ํ๋กฌํํธ ์ธ์ ์ , ์ ํด ์ฝํ ์ธ , ๊ณ ์ ๊ด๋ , ์๋ชป๋ ์ ๋ณด ๋ฑ์ ๋ค๋ฃน๋๋ค.
Giskard Scan์ ์ฌ์ฉํ์ฌ ๋ค์์ ์ํํ ์ ์์ต๋๋ค:
- ์์ด์ ํธ ๋ ๋ ํ โ OWASP LLM Top-10 ์ํ ๋ฒ์ฃผ์ ๊ฑธ์ณ ์ ๋์ ์ ๋ ฅ ์๋ ์์ฑ
- ํ๋กฌํํธ ์ธ์ ์ ํ๋ก๋ธ ์คํ โ ์ฆ์ ์ฌ์ฉ ๊ฐ๋ฅํ ์ธ์ ์ ํ์ด๋ก๋ ๋ด์ฅ ๋ฐ์ดํฐ์
- ์ฌ์ฉ์ ์ ์ ์์ฑ๊ธฐ๋ก ํ์ฅ โ
generate_suite์ ์์ฒดScenarioGenerator์ธ์คํด์ค๋ฅผ ์ ๋ฌํ๊ฑฐ๋vulnerability_suite_generator_registry์ ๋ฑ๋ก
๋น ๋ฅธ ์์
import asyncio
from giskard.scan import vulnerability_scan
async def my_agent(inputs: str) -> str:
# ์์ด์ ํธ / ๋ชจ๋ธ ํธ์ถ๋ก ๊ต์ฒด
return f"Echo: {inputs}"
async def main() -> None:
await vulnerability_scan(
target=my_agent,
description="A customer support chatbot for an e-commerce platform.",
languages=["en"],
)
asyncio.run(main())
์ค์บ ์์ฑ๊ธฐ์๋ ์์ Checks ํ์ ๊ณผ ๋์ผํ๊ฒ LLM provider extra์ API ํค๋ ํ์ํฉ๋๋ค.
Giskard v2๋ฅผ ์ฐพ๊ณ ๊ณ์ ๊ฐ์?
Giskard v2์๋ Scan(์๋ ์ทจ์ฝ์ ํ์ง)๊ณผ RAGET(RAG ํ๊ฐ ํ ์คํธ ์ธํธ ์์ฑ)์ด ํฌํจ๋์ด ์์์ต๋๋ค.
LLM ์์ด์ ํธ์ ๊ฒฝ์ฐ, ๋ ๋ค v3์์ giskard-scan์ผ๋ก ๋์ฒด๋์์ต๋๋ค: v2 LLM ์ค์บ ๋์ vulnerability_scan์ ์ฌ์ฉํ๊ณ , RAGET ๋์ quality_scan(KnowledgeBase ํฌํจ)์ ์ฌ์ฉํ์ธ์.
v3๋ ML ๋ชจ๋ธ์์๋ ์๋ํฉ๋๋ค. ๋ชจ๋ธ์ target์ผ๋ก ๋ํํ๊ณ giskard-checks ๋๋ giskard-scan์ผ๋ก ํ๊ฐํ์ธ์. ์๋ ์์ ๊ฐ ๋ค๋ฃจ๋ ๊ฒ์ v2 ์ ์ฉ ์๋ ํ
์ด๋ธ ํ์ ์ค์บ์
๋๋ค. ์ด๋ giskard.Model + giskard.Dataset์ ๊ฒ์ฌํ์ฌ ์ฑ๋ฅ, ํธํฅ ๋ฐ ๊ฒฌ๊ณ ์ฑ ๋ฌธ์ ๋ฅผ ์๋ ๊ฐ์งํ๋ ํ์ง๊ธฐ ์ค์ํธ์ด๋ฉฐ, giskard.testing ML ํ
์คํธ ์ค์ํธ์ Giskard Hub๋ ํฌํจํฉ๋๋ค. ์ด๋ฌํ ๊ธฐ๋ฅ์ v3์ ๊ณํ๋์ด ์์ง ์์ต๋๋ค.
pip install "giskard[llm]>2,<3"
Scan โ ์ฑ๋ฅ, ํธํฅ ๋ฐ ๋ณด์ ๋ฌธ์ ์๋ ๊ฐ์ง
๋ชจ๋ธ์ ๋ํํ๊ณ ์ค์บ์ ์คํํ์ธ์:
import giskard
import pandas as pd
# my_llm_chain์ ์ค์ LLM ์ฒด์ธ ๋๋ ๋ชจ๋ธ ์ถ๋ก ๋ก์ง์ผ๋ก ๊ต์ฒด
def model_predict(df: pd.DataFrame):
"""์ด ํจ์๋ DataFrame์ ๋ฐ์ ์ถ๋ ฅ ๋ชฉ๋ก(ํ๋น ํ๋)์ ๋ฐํํด์ผ ํฉ๋๋ค."""
return [my_llm_chain.run({"query": question}) for question in df["question"]]
giskard_model = giskard.Model(
model=model_predict,
model_type="text_generation",
name="My LLM Application",
description="A question answering assistant",
feature_names=["question"],
)
scan_results = giskard.scan(giskard_model)
display(scan_results)
RAGET โ RAG ์ ํ๋ฆฌ์ผ์ด์ ์ฉ ํ๊ฐ ๋ฐ์ดํฐ์ ์์ฑ
์ง์ ๋ฒ ์ด์ค์์ ์ง๋ฌธ, ์ฐธ์กฐ ๋ต๋ณ ๋ฐ ์ปจํ ์คํธ๋ฅผ ์๋ ์์ฑ:
import pandas as pd
from giskard.rag import generate_testset, KnowledgeBase
# ์ง์ ๋ฒ ์ด์ค ๋ฌธ์ ๋ก๋
df = pd.read_csv("path/to/your/knowledge_base.csv")
knowledge_base = KnowledgeBase.from_pandas(df, columns=["column_1", "column_2"])
testset = generate_testset(
knowledge_base,
num_questions=60,
language="en",
agent_description="A customer support chatbot for company X",
)
๐ ์ปค๋ฎค๋ํฐ
AI ์ปค๋ฎค๋ํฐ์ ๊ธฐ์ฌ๋ฅผ ํ์ํฉ๋๋ค! ์ด ๊ฐ์ด๋๋ฅผ ์ฝ๊ณ ์์ํ๊ณ , Discord์์ ํ๋ฐํ ์ปค๋ฎค๋ํฐ์ ์ฐธ์ฌํ์ธ์.
์งํ ์ํฉ์ ํ๋ก์ฐํ๊ณ ํผ๋๋ฐฑ์ ๊ณต์ ํ์ธ์: v3 ๋ฐํ ยท ๋ก๋๋งต
๐ ๋ณํ๋ฅผ ๋จ๊ฒจ์ฃผ์ธ์, ํ๋ก์ ํธ๊ฐ ๋ค๋ฅธ ์ฌ๋๋ค์๊ฒ ๋ฐ๊ฒฌ๋๊ณ ๋ฉ์ง ์คํ์์ค ๋๊ตฌ๋ฅผ ๊ตฌ์ถํ๋ ๋ฐ ๋๊ธฐ๋ถ์ฌ๊ฐ ๋ฉ๋๋ค! ๐
โค๏ธ ์ ํฌ ์์ ์ด ์ ์ฉํ๋ค๊ณ ์๊ฐ๋์๋ฉด GitHub์์ ํ์์ ๊ณ ๋ คํด ์ฃผ์ธ์. ์๊ฐ ํ์์ ํตํด ์คํฐ์ ๋ฐฐ์ง๋ฅผ ๋ฐ๊ณ , ์ด readme์ ํ์ฌ๋ฅผ ํ์ํ๋ฉฐ, ๋ฒ๊ทธ ๋ณด๊ณ ๋ฅผ ์ฐ์ ์ฒ๋ฆฌ๋ฐ์ ์ ์์ต๋๋ค. ๋ํ ์ปจ์คํ ํ๋ก์ ํธ ์ฐธ์ฌ, ์ํฌ์ ์งํ ๋๋ ํ์ฌ์์ ๊ฐ์ฐ์ ์ํ์๋ฉด ์ผํ์ฑ ํ์๋ ์ ๊ณตํฉ๋๋ค.