ç§ãã¡ã¯ä»ãã瀟å ã®ç¥èããŒã¹ãã«ã¹ã¿ããŒãµããŒãã·ã¹ãã ãã³ãŒãã¬ãã¥ãŒããããªã©ãããããæè¡åéã§GenAIãæŽ»çšããŠããŸãããããŠãã»ãšãã©ãã¹ãŠã®ã±ãŒã¹ã§ã誰ããæçµçã«ããåããããŸã:
ãŠãŒã¶ãŒãèŠãŠã¯ãããªããã®ãã¢ãã«ãè¿åããªãã®ããäœãæ¢ããã®?ã
ããã¯ãRAGæ©èœãAIãšãŒãžã§ã³ããæ§ç¯ããäŒæ¥ãæçµçã«çŽé¢ããé害ã§ããããŠãŒã¶ãŒãã¢ã¯ã»ã¹æš©éã®ãªãææžããLLMãããŒã¿ãè¿ãç¬éã§ããããã¹ãŠã®é¢ä¿è ã«æ³çã財åçãè©å€äžã®ãªã¹ã¯ãããããç¬éã§ããæ®å¿µãªãããåŸæ¥ã®èªå¯æ¹æ³ã¯RAGã«ãããéå±€çãã€åçãªã¢ã¯ã»ã¹å¶åŸ¡ã®æ§è³ªã«ã¯é©ããŠããŸããããŸãã«ããã§ã SpiceDB ã®ãããªçŸä»£çãªèªå¯æš©éã·ã¹ãã ãèŒãç¹ã¯ãAIæèŒã¢ããªã±ãŒã·ã§ã³ã«ãããã³ã³ãã³ãã®ãã£ã«ã¿ãªã³ã°ã®ããã®çްããèªèšŒãæ§ç¯ããç¹ã§ãã
å®éãOpenAIã¯SpiceDBã䜿ã£ãŠãGoogle DriveãDropboxãGitHubãªã©æ§ã ãªãœãŒã¹ããããŒã¿ãChatGPTã«åãèŸŒãæ©èœã§ããChatGPTã³ãã¯ã¿ãŒãå©çšãã5çŸäžãŠãŒã¶ãŒã®ããã«ã37ååä»¶ã®ææžãä¿è·ããŠããŸãã
ãã®ããã°èšäºã§ã¯ãSpiceDBãš Testcontainers ãçµã¿åãããããšã§ãRAGãã€ãã©ã€ã³å ã§æš©éããžãã¯ããšã³ãããŒãšã³ãã§èªåçã«ãã¹ãã§ããæ¹æ³ã玹ä»ããŠããŸããã€ã³ãã©äŸåé¢ä¿ã¯ãŒãã§ãããªããžããªã®äŸã¯ ãã¡ãã§ã芧ããã ããŸãã
æ¿èªã«é¢ããç°¡åãªå ¥é
å®è£ ã«å ¥ãåã«ããŸã2ã€ã®åºæ¬çãªæŠå¿µãæç¢ºã«ããŸããã: èªèšŒ(ãŠãŒã¶ãŒã®èªèšŒ)ãš èªå¯( ã¢ã¯ã»ã¹ å¯èœãªãã®ã決å®ãã ããš)ã
èªå¯ã¯äžè¬çã«ä»¥äžã®æè¡ã§å®è£ ãããŸã:
- ã¢ã¯ã»ã¹å¶åŸ¡ãªã¹ã(ACL)
- ããŒã«ããŒã¹ã¢ã¯ã»ã¹å¶åŸ¡(RBAC)
- 屿§ããŒã¹ã¢ã¯ã»ã¹å¶åŸ¡(ABAC)
ããããRAGãã€ãã©ã€ã³ã®ãããªè€éã§åçãã€æèè±ããªã¢ããªã±ãŒã·ã§ã³ã§ã¯ãRBACãABACãšãã£ãåŸæ¥ã®ææ³ã¯äžååã§ããæ°ãã«ç»å Žãã ReBAC (Relationship-Based Access Control)ã¯ãåºå®ã«ãŒã«ã§ã¯ãªã é¢ä¿ã®ã°ã©ããšããŠã¢ã¯ã»ã¹ ãã¢ãã«åããå¿ èŠãªæè»æ§ãšã¹ã±ãŒã©ããªãã£ãæäŸããããçæ³çã§ãã
ReBACã¯ãGoogleããã¹ãŠã®è£œå(äŸ:Google DocsãDrive)ã«ãããæš©éã管çããããã«æ§ç¯ããå éšèªèšŒã·ã¹ãã ãGoogle Zanzibarã§åºãŸããŸãããã¶ã³ãžãã«ã·ã¹ãã ã¯äœé å»¶ãé«ã¹ã«ãŒãããã®èªå¯ãã§ãã¯ããããŠã°ããŒãã«ãªäžè²«æ§ã«æé©åãããŠããããããã¯RAGã·ã¹ãã ã«é©ããèŠä»¶ã§ãã
SpiceDB ã¯Googleã®ZanzibarèªèšŒã¢ãã«ã®äžã§æãã¹ã±ãŒã©ãã«ãªãªãŒãã³ãœãŒã¹å®è£ ã§ããã¢ã¯ã»ã¹ã¯é¢ä¿ã°ã©ããšããŠä¿åãããåºæ¬çãªãã§ãã¯ã¯æ¬¡ã®ããã«ç°¡çŽãããŸã:Â
ãã? ä¿³åª ãããèš±å¯ãããŠããŸã ã¢ã¯ã·ã§ã³ ããã«ã€ã㊠ãªãœãŒã¹?
Googleããã¥ã¡ã³ã颚ã®äŸãšããŠ:
definition user {}
definition document {
relation reader: user
relation writer: user
permission read = reader + writer
permission write = writer
}
ãã®ã¹ããŒãã¯ãªããžã§ã¯ãã¿ã€ã(user ããã³ document)ããªããžã§ã¯ãéã®æç€ºç㪠é¢ä¿ (readerã writer)ãããã³æŽŸç æš©é (readã write)ãå®çŸ©ããŸããSpiceDBã¯é¢ä¿ã°ã©ãããã€ã¯ãç§åäœã§è©äŸ¡ããå€§èŠæš¡ã«ãªã¢ã«ã¿ã€ã ã®èªå¯ãã§ãã¯ãå¯èœã«ããŸãã
RAGã®ã¢ã¯ã»ã¹å¶åŸ¡Â
RAG(Retrieval-Augmented Generation)ã¯ãå€§èŠæš¡èšèªã¢ãã«(LLM)ãå€éšã®ç¥èããŒã¹ãåç §ã§ããããã«ããããšã§åŒ·åããã¢ãŒããã¯ãã£ãã¿ãŒã³ã§ãããé垞㯠Retriever ã³ã³ããŒãã³ããææžã®ãã£ã³ã¯ãèŠã€ããLLMãæ å ±ã«åºã¥ãå¿çãçæãããšããåœ¢ã§æ©èœããŸãã
ãã®ãã¿ãŒã³ã¯çŸåšãäŒæ¥ãäŒæ¥ã§ãã£ãããããã®ãããªé¡§å®¢ãã¬ã€ããã¯ãå人æ å ±(PII)ãªã©ã®æ©å¯ããŒã¿ãç §äŒããã¢ããªã«äœ¿ãããŠããããã¹ãŠæ§èœåäžã®ããã«ãã¯ã¿ãŒããŒã¿ããŒã¹ã«ä¿åãããŠããŸãããããããã®ãããŒã«ãããæ ¹æ¬çãªãªã¹ã¯ã¯ ããŒã¿ãªãŒãã¥ãžã§ããRetrieverã³ã³ããŒãã³ãã¯æš©éãç¡èŠããLLMã¯äžæ£ãªããŒã¿ãåãã§èŠçŽããŸããå®éãOWASPã«ã¯ãSensitive Information Disclosure(æ©å¯æ å ±é瀺)ãéå°ãªãšãŒãžã§ã³ã·ãŒ&ãã¯ãã«(Agency and Vector)ãåã蟌ã¿ã®åŒ±ç¹(Embbedding Weaknesses)ããªã©ã®ãLarge Language Model Applicationsã®ãªã¹ã¯ããã10ãªã¹ããããããŸãããã®æŒæŽ©ã®åœ±é¿ã¯æ·±å»ã§ããã顧客ã®ä¿¡é Œåªå€±ããã³ã³ãã©ã€ã¢ã³ã¹éåã«ããå·šé¡ã®çµæžçã»è©å€çæå®³ã«è³ããŸã§å€å²ã«ããããŸãã
ãã®ã»ããã¢ããã¯çްããèªèšŒãåå®ã«å¿ èŠãšããŠãããããã§ SpiceDB ã®ç»å Žã§ããSpiceDBã¯ãæ€çŽ¢ããææžããªã¢ã«ã¿ã€ã ã®èªå¯ãã§ãã¯ã§åŸãããã£ã«ã¿ãŒããæ€çŽ¢ãŠãŒã¶ãŒãé²èЧã§ããããŒã¿ã®ã¿ãã¢ãã«ã䜿çšããããã«ããŸããå¯äžã®èŠä»¶ã¯ãæ å ±ã®åºæã瀺ã ã¡ã¿ããŒã¿ ãææžã«èšèŒãããŠããããšã§ããããããã¢ãã¯ãæåã®Dockerã»ããã¢ãããäžå®å®ãªç¶ç¶ççµ±å(CI)ç°å¢ãªãã«ãã®éèŠãªæš©éããžãã¯ããã¹ãããã®ã¯é£ããã§ããTestcontainers ã¯å®ç§ãªãœãªã¥ãŒã·ã§ã³ãæäŸãããŠããããã¹ãå ã§å®éã®å®çšã¬ãã«ã®äœ¿ãæšãŠSpiceDBã€ã³ã¹ã¿ã³ã¹ãç«ã¡äžããRAGãã€ãã©ã€ã³ããšã³ãããŒãšã³ãã§æš©éãå°éããŠããããšã決å®è«çã«æ€èšŒã§ããŸãã
ãã¹ãŠã®ãã¹ãã«å¯ŸããŠå®éã®èªèšŒãã¹ãã³ã¢ãããã
èªèšŒã·ã¹ãã ãæš¡æ¬ããããã¯ãŒã¯ã¹ããŒã·ã§ã³ã§æåã§å®è¡ãã代ããã«ããã¹ãã«æ¬¡ã®ã³ãŒãã©ã€ã³ã远å ã§ããŸã:
container, _ := spicedbcontainer.Run(ctx, "authzed/spicedb:v1.47.1")
ãããŠTestcontainersã¯ä»¥äžã®ããšãããŸã:
- å®éã®SpiceDBç»åãååŸããŠãã ãã
- æž æœã§éé¢ãããç°å¢ã§å§ããŠãã ãã
- åçããŒããå²ãåœãŠãŠãã ãã
- æºåãã§ããã®ãåŸ ã£ãŠ
- gRPCãšã³ããã€ã³ããæž¡ããŠãã ãã
- åŸçä»ã
Testcontainersã¯ã³ã³ããã®ååŸãåçããŒãã®å ¬éãèªåçãªåé€ãŸã§ã©ã€ããµã€ã¯ã«å šäœãåŠçãããããDockerã³ãã³ãã®å®è¡ãã¯ãªãŒã³ã¢ããã¹ã¯ãªããã®äœæãªã©ã®æåããã»ã¹ãäžèŠã«ã§ããŸãããã®éé¢ã«ããããã¹ãŠã®ãã¹ããæ°é®®ã§ã¯ãªãŒã³ãªèªå¯ã°ã©ãã§å®è¡ãããããŒã¿ã®ç«¶åãé²ããæš©éãã¹ããIDEã䞊åç¶ç¶ççµ±å(CI)ãã«ãå šäœã§ å®å šã«åçŸå¯èœ ã«ãªããŸãã
çªç¶ããŠããããã¹ãã®äžã«æ¬ç©ã®æ¬æ Œçãªãµã³ãžãã«é¢šã®èš±å¯ãšã³ãžã³ãå ¥ããŸããÂ
SpiceDBãšTestcontainerã®äœ¿çš
ããã§ã¯ãSpiceDBãšTestcontainersã䜿ã£ãŠãšã³ãããŒãšã³ãã®æš©éãã¹ããå®çŸããæ¹æ³ã®ãŠã©ãŒã¯ã¹ã«ãŒã瀺ããŸãããã®ãã¥ãŒããªã¢ã«ã®ãœãŒã¹ã³ãŒã㯠ãã¡ãã§ã芧ããã ããŸãã
1ãRAGã®ãã¹ãÂ
ç°¡æœã«ããããã«ãæå°éã®RAGãæã¡ãæ€çŽ¢ã¡ã«ããºã ãç°¡åã§ããÂ
ã¡ã¿ããŒã¿ãšããŠæ©èœãã3ã€ã®ææžããã¹ãããŸããdoc_ids(doc1 doc2 ...)ã䜿ããŸããÂ
doc1:å éšããŒããããdoc2: ã«ã¹ã¿ããŒãã¬ã€ããã¯doc3: å ¬éFAQ
ãããŠ3人ã®ãŠãŒã¶ãŒ:
- ãšããªã¢ã¯ææããŠããŸã
doc1 - ãã¢ããªã¹ã¯èŠãããšãã§ããŸã
doc2 - ãã£ãŒãªãŒ(ãŸãã¯èª°ã§ã)ã¯é²èЧå¯èœã§ã
doc3
ãã®SpiceDBã¹ããŒã㯠user ãš document ãªããžã§ã¯ãã¿ã€ããå®çŸ©ããŠããŸãããŠãŒã¶ãŒãææžã®çŽæ¥viewerãŸãã¯ownerã§ããå Žåããã®ææžã«å¯ŸããŠreadæš©éãæã¡ãŸãã
definition user {}
definition document {
relation owner: user
relation viewer: user | owner
permission read = owner + viewer
}
2ããã¹ãã³ã³ããã®èµ·åÂ
ã³ãŒãã®äžè¡ãäœ¿ãæšãŠã®SpiceDBã€ã³ã¹ã¿ã³ã¹ãèµ·åãããã¹ããéå§ããæ¹æ³ã¯ä»¥äžã®éãã§ã:
container, err := spicedbcontainer.Run(ctx, "authzed/spicedb:v1.47.1")
require.NoError(t, err)
次ã«ãå®è¡äžã®ã³ã³ããåãµãŒãã¹ã«æ¥ç¶ããŸãã
host, _ := container.Host(ctx)
port, _ := container.MappedPort(ctx, "50051/tcp")
endpoint := fmt.Sprintf("%s:%s", host, port.Port())
client, err := authzed.NewClient(
endpoint,
grpc.WithTransportCredentials(insecure.NewCredentials()),
grpcutil.WithInsecureBearerToken("somepresharedkey"),
)
ããã¯ãã¹ãã©ã³ããŒå ã§åäœããå®å šã«æ©èœããSpiceDBã€ã³ã¹ã¿ã³ã¹ã§ãã
3ãã¹ããŒã+ãã¹ãããŒã¿ãèªã¿èŸŒã
ãã¹ãã¯ã¢ããªã±ãŒã·ã§ã³ãšåãæ¹æ³ã§ããŒã¿ãã·ãŒãããŸã:
_, err := client.WriteSchema(ctx, &apiv1.WriteSchemaRequest{Schema: schema})
require.NoError(t, err)
ãããããïŒ
rel("document", "doc1", "owner", "user", "emilia")
rel("document", "doc2", "viewer", "user", "beatrice")
rel("document", "doc3", "viewer", "user", "emilia")
rel("document", "doc3", "viewer", "user", "beatrice")
rel("document", "doc3", "viewer", "user", "charlie")
çŸåšããã¹ãŠã®ãã¹ãã©ã³ã«å¯ŸããŠäºæž¬å¯èœã§åçŸå¯èœãªèªå¯ã°ã©ããæã«å ¥ããŸããã
4ãSpiceDBã«ããåŸãã£ã«ã¿ãªã³ã°
LLMãäœããèŠãåã«ãææžå ã®æš©éã®çå®ã®æ å ±æºãšããŠæ©èœããSpiceDBã§æš©éã確èªããŸãã
resp, err := r.spiceClient.CheckPermission(ctx, &apiv1.CheckPermissionRequest{
Resource: docObject,
Permission: "read",
Subject: userSubject,
})
ããSpiceDBã ããããããšèšã£ãå Žåãããã¥ã¡ã³ãã¯LLMã«å ¥åãããããŠãŒã¶ãŒãèªããæš©éã«åºã¥ããŠã¯ãšãªãžã®åçãåŸãããšãä¿èšŒãããŸãã
ããã«ããã以äžã®ããšãåé¿ãããŸã:
- å¶çºçãªããŒã¿æŒæŽ©
- éå°èš±å®¹ãã¯ãã«æ¢çŽ¢
- ã³ã³ãã©ã€ã¢ã³ã¹ã®åé¡
åŸæ¥ã®ã¢ã¯ã»ã¹å¶åŸ¡ã¯ããŒã¿ãåã蟌ã¿ã«ãªããšæ©èœããªããªããããã¬ãŒãã¬ãŒã«ãããããšã§ãããé²ããŸããÂ
åäžã®ãã¹ãã«ããããšã³ãããŒãšã³ãã®èš±å¯ãã§ãã¯
以äžããã¹ãã®å®å šãªäž»åŒµã§ã:
ãšããªã¢ã¯ãããŒããããããåãåããâ doc1
ã ã£ãŠ åœŒãã¯ãªãŒããŒã ããã
ãã¢ããªã¹ã¯ããã¬ã€ããã¯ããå°ãâ doc2
圌女ã¯èŠèŽè
ã ããã§ãã
ãã£ãŒãªãŒã¯ãpublicããšåãåããâ doc3
ããã¯åœŒ ãèªããå¯äžã®ææžã§ãå
¬ææžã ããã§ã
åäžã®å€±ææš©éã«ãŒã«ãããå Žåããšã³ãããŒãšã³ããã¹ãã¯å³åº§ã«å€±æããŸããããã¯RAGãã€ãã©ã€ã³ã®æ°ããååŸã¢ãŒããåã蟌ã¿ãããã¥ã¡ã³ãã¿ã€ããæš©éã«ãŒã«ãªã©çµ¶ãã倿Žãããããéåžžã«éèŠã§ããÂ
ããRAGãã€ãã©ã€ã³ãGoã«å ¥ã£ãŠããªãã£ããã©ãããŸãã?
ãŸãã SpiceDB Go Testcontainersã¢ãžã¥ãŒã« ãžã®ãªãªãžãã«è²¢ç®ããã Guillermo Mariscal ã«æè¬ããŸããÂ
ããããªãã®RAGãã€ãã©ã€ã³ãPythonãªã©å¥ã®èšèªã§æžãããŠãããã©ãã§ãããã?å¿é ããªãã§ãã ãããPythonã§æžãããã³ãã¥ããã£ã®Testcontainersã¢ãžã¥ãŒã«ãåæ§ã«äœ¿ããŸããã¢ãžã¥ãŒã«ã¯ ãã¡ãã§ã芧ããã ããŸãã
éåžžãçµ±åãã¹ãã§ã¯æ¬¡ã®ããã«ç©åããŸãã
# Your RAG pipeline test
def test_rag_pipeline_respects_permissions():
with SpiceDBContainer() as spicedb:
# Set up permissions schema
client = create_spicedb_client(
spicedb.get_endpoint(),
spicedb.get_secret_key()
)
# Load your permissions model
client.WriteSchema(your_document_permission_schema)
# Write test relationships
# User A can access Doc 1
# User B can access Doc 2
# Test RAG pipeline with User A
results = rag_pipeline.search(query="...", user="A")
assert "Doc 1" in results
assert "Doc 2" not in results # Should be filtered out!
Goã¢ãžã¥ãŒã«ãšåæ§ã«ããã®ã³ã³ããã¯ãã¹ãŠã®ãã¹ãå®è¡ã§ã¯ãªãŒã³ã§å€ç«ããSpiceDBã€ã³ã¹ã¿ã³ã¹ãæäŸããŸãã
ãªããã®ã¢ãããŒããéèŠãªã®ã
RAGãã€ãã©ã€ã³ã«ãããèªå¯ãã¹ãã¯ãèŠæš¡ãé å»¶ã®èŠä»¶ãããããè€éã«ãªãåŸãŸãããæ©å¯ããŒã¿ãæ±ãã·ã¹ãã ã§ã¯ããã«è€éã«ãªãããšããããŸããSpiceDBã®æè»æ§ãšã¹ã±ãŒã«ãTestcontainerã®èªååãããå€ç«ããç°å¢ãšçµ±åããããšã§ãå®å šã«ä¿¡é Œæ§ãé«ãæ±ºå® è« çãªèªèšŒã¢ãããŒããžãšç§»è¡ããŸããÂ
ã³ãŒããåºè·ããããã³ã«ãæ°ããæ¬çªç°å¢ã®èªå¯ãšã³ãžã³ãèµ·åããããã¹ãããŒã¿ãèªã¿èŸŒãŸãããããã«åè§£ãããããã éçºãã·ã³ãšCIéã®ããªãããäžåãããŸããããã®ãã¿ãŒã³ã«ãããRAGã·ã¹ãã ã¯3ã€ã®ããã¥ã¡ã³ãããæ°çŸäžãã®ææžã«ã¹ã±ãŒã«ããéãå®å šã§æ£ç¢ºãã€èš±å¯ãèªèãããã®ã«ãªããŸãã
èªåã§è©ŠããŠã¿ã
Goã®å®å
šãªåäœäŸãšãµã³ãã«RAGãã€ãã©ã€ã³ã¯ãã¡ãã§ã:
https://github.com/sohanmaheshwar/spicedb-testcontainer-rag
ã¯ããŒã³ã ãgo test -vèµ°ãã
æ°ããSpiceDBã€ã³ã¹ã¿ã³ã¹ãèµ·åããæš©éãããŒãããRAGã®åäœã䞻匵ããæ§åãèŠãŠãã ããã
ãŸãã Go ã Pythonã§SpiceDBã®testcontainerã®ã³ãã¥ããã£ã¢ãžã¥ãŒã«ãèŠã€ããŠã¿ãŠãã ããã