[HybridAGI ] Agent의 행동을 그래프 기반으로 최적화할 수 있는 오픈소스
https://github.com/SynaLinks/HybridAGI
GitHub - SynaLinks/HybridAGI: The Programmable Cypher-based Neuro-Symbolic AGI that lets you program its behavior using Graph-ba
The Programmable Cypher-based Neuro-Symbolic AGI that lets you program its behavior using Graph-based Prompt Programming: for people who want AI to behave as expected - SynaLinks/HybridAGI
github.com
소개
인공지능(AI) 분야가 발전함에 따라, 복잡한 작업을 수행하는 AI 에이전트에 대한 수요가 증가하고 있습니다. 이러한 에이전트는 전통적으로 사용자의 개입 없이 스스로 학습하고 행동하는 방식으로 설계되었지만, 최근에는 사용자의 제어와 설명 가능성을 강조하는 새로운 접근 방식이 등장하고 있습니다. 이 글에서는 그래프 기반 프롬프트 프로그래밍을 통해 AI 에이전트를 효과적으로 제어하는 HybridAGI 프레임워크와 DSPy 라이브러리에 대해 자세히 알아보겠습니다.
HybridAGI란 무엇인가요?
HybridAGI는 AgentOS 프레임워크를 기반으로 하는 설명 가능하고 결정적인 에이전트 시스템입니다. 기존 에이전트 시스템과 달리, HybridAGI는 인간의 개입과 통제를 중요하게 생각하며, 최소한의 fine-tuning으로 에이전트의 동작을 효과적으로 제어할 수 있도록 설계되었습니다.
HybridAGI의 핵심 기능
- 그래프 기반 프롬프트 프로그래밍: 에이전트의 행동과 의사 결정을 그래프 형태로 프로그래밍할 수 있는 Cypher 언어를 이용합니다. 이를 통해 사용자는 에이전트의 동작을 직관적으로 이해하고 제어할 수 있습니다.
- 자동 최적화: 학습 데이터와 예시를 활용하여 프롬프트를 자동으로 최적화합니다.
- 하이브리드 메모리: 벡터 데이터베이스와 그래프 데이터베이스를 결합하여 에이전트의 지식을 효율적으로 관리합니다.
HybridAGI의 장점
- 설명 가능성: 그래프 기반 프로그래밍을 통해 에이전트의 행동을 명확하게 이해하고 설명할 수 있습니다.
- 제어 가능성: 사용자는 프로그래밍을 통해 에이전트의 행동을 직접 제어할 수 있습니다.
- 효율성: 최소한의 fine-tuning과 prompt engineering으로 에이전트를 효과적으로 제어할 수 있습니다.
HybridAGI의 메모리 시스템
HybridAGI는 효율적인 에이전트 구현을 위해 다양한 메모리 시스템을 활용합니다. 각 메모리 시스템은 그래프 기반 구조를 사용하여 데이터를 효율적으로 관리하고 분석합니다.
- Program Memory (Dependency Graph): 코드 실행 과정 및 의존성 관리
- Document Memory (Document/Chunk Tree): 문서 데이터 계층적 관리 및 검색
- Fact Memory (Knowledge Graph): 정보 및 관계 저장, 시각화 및 추론
- Trace Memory (Program Traces): 프로그램 실행 흐름 기록, 디버깅 및 최적화
Langgraph와의 차이
- langgraph: 사용자가 state로 정의 → 정적이고 이걸 수정할 방법이 없음
- HybridAGI는 Cypher 언어를 통해 LLM이 스스로 수정할 수 있음
큰틀은 Langgraph를 짜되 detail한 reasoning은 HybridAGI의 방식이 좋을 수 있음
HybridAGI 그리고 Human-Robot Interactions
https://youtu.be/6gdYi-UKYTI?si=f2JiGKppcIyDT0bp
DSPy: HybridAGI에서 활용하는 프롬프트 기법
DSPy (Declarative Self-improving Python)는 HybridAGI 프레임워크에서 사용되는 파이썬 패키지입니다. DSPy는 기존 프롬프트 기반 접근 방식의 한계를 극복하고, 사용자가 더욱 효율적으로 AI 시스템을 구축하고 최적화할 수 있도록 설계되었습니다.
DSPy의 주요 특징
- 코드 기반 모듈 설계: 문자열 템플릿 대신 코드를 사용하여 AI 시스템의 동작을 정의합니다.
- 자동 최적화: 프롬프트와 모델 가중치를 자동으로 조정하여 성능을 극대화합니다.
- 유연성과 확장성: 사용자가 데이터와 파이프라인에 맞춰 최적화된 프롬프트를 생성할 수 있는 유연한 환경을 제공합니다.
DSPy의 장점
- 효율성: 최소한의 리소스로 사용자가 목적을 달성할 수 있도록 합니다.
- 유연성: 다양한 언어 모델과의 상호 작용을 최적화할 수 있습니다.
- 확장성: 사용자가 직접 프로그램을 구현하고 확장할 수 있습니다.
결론
HybridAGI와 DSPy는 그래프 기반 프롬프트 프로그래밍을 통해 AI 에이전트를 효과적으로 제어하고 최적화하는 강력한 도구입니다. 이러한 기술은 앞으로 더욱 복잡하고 정교한 AI 시스템을 구축하는 데 중요한 역할을 할 것으로 기대됩니다.
HybridAGI 실습: 영화 데이터
input data
input_data = [
{
"Title": "The Shawshank Redemption",
"URL": "<https://www.imdb.com/title/tt0111161/>",
"Summary": "A man wrongly imprisoned finds hope and friendship during his life sentence.",
"Category": ["Drama", "Crime"],
"Ratings": 9.3
},
{
"Title": "The Godfather",
"URL": "<https://www.imdb.com/title/tt0068646/>",
"Summary": "An organized crime dynasty's aging patriarch transfers control to his reluctant son.",
"Category": ["Crime", "Drama"],
"Ratings": 9.2
},
{
"Title": "The Dark Knight",
"URL": "<https://www.imdb.com/title/tt0468569/>",
"Summary": "Batman faces the Joker, a criminal mastermind who wreaks havoc on Gotham.",
"Category": ["Action", "Crime", "Drama"],
"Ratings": 9.0
},
{
"Title": "Pulp Fiction",
"URL": "<https://www.imdb.com/title/tt0110912/>",
"Summary": "The lives of two mob hitmen, a boxer, and a gangster's wife intertwine in crime.",
"Category": ["Crime", "Drama"],
"Ratings": 8.9
},
{
"Title": "Schindler's List",
"URL": "<https://www.imdb.com/title/tt0108052/>",
"Summary": "A businessman saves the lives of more than a thousand Polish Jews during WWII.",
"Category": ["Drama", "History", "War"],
"Ratings": 8.9
},
{
"Title": "Forrest Gump",
"URL": "<https://www.imdb.com/title/tt0109830/>",
"Summary": "A slow-witted man witnesses and influences key historical events in the 20th century.",
"Category": ["Drama", "Romance"],
"Ratings": 8.8
},
{
"Title": "Inception",
"URL": "<https://www.imdb.com/title/tt1375666/>",
"Summary": "A thief who steals secrets through dream-sharing must plant an idea into a CEO's mind.",
"Category": ["Action", "Adventure", "Sci-Fi"],
"Ratings": 8.8
}
]
input_facts = dt.FactList()
for data in input_data:
link = dt.Entity(name=data["URL"], label="Link")
title = dt.Entity(name=data["Title"], label="Title")
summary = dt.Entity(name=data["Summary"], label="Summary")
input_facts.facts.append(dt.Fact(subj=link, rel=dt.Relationship(name="HAS_TITLE"), obj=title))
input_facts.facts.append(dt.Fact(subj=link, rel=dt.Relationship(name="HAS_SUMMARY"), obj=summary))
for category in data["Category"]:
category_entity = dt.Entity(name=category, label="Category")
input_facts.facts.append(dt.Fact(subj=link, rel=dt.Relationship(name="BELONGS_TO_CATEGORY"), obj=category_entity))
rating = dt.Entity(name=str(data["Ratings"]), label="Ratings")
input_facts.facts.append(dt.Fact(subj=link, rel=dt.Relationship(name="HAS_RATING_OF"), obj=rating))
URL, Title, Summary, Category노드의 라벨 정의 및 노드와 노드 간의 Relationship 정의
from hybridagi.memory.integration.local import LocalFactMemory
fact_memory = LocalFactMemory(index_name="movies_data")
fact_memory.update(input_facts)
fact_memory.show(notebook=True)
Fact Memory에 적재
from hybridagi.core.pipeline import Pipeline
from hybridagi.embeddings import SentenceTransformerEmbeddings
from hybridagi.modules.deduplicators import EntityDeduplicator
from hybridagi.modules.embedders import EntityEmbedder, FactEmbedder
pipeline = Pipeline()
embeddings = SentenceTransformerEmbeddings(
model_name_or_path = "all-MiniLM-L6-v2",
dim = 384, # The dimention of the embeddings vector (also called dense vector)
)
pipeline.add("deduplicate_entities", EntityDeduplicator(method="exact"))
pipeline.add("embed_entities", EntityEmbedder(embeddings=embeddings))
pipeline.add("embed_facts", FactEmbedder(embeddings=embeddings))
output_facts = pipeline(input_facts)
fact_memory.update(output_facts) # Update the fact memory with our cleaned data
fact_memory.show(notebook=True)
import hybridagi.core.graph_program as gp
main = gp.GraphProgram(
name = "main",
description = "The main program",
)
main.add(gp.Action(
id = "fact_search",
purpose = "Find relevant facts",
tool = "FactSearch",
prompt = "Please infer the similarity search query (only ONE item) based on the Objective's question",
))
main.add(gp.Action(
id = "answer",
purpose = "Answer the Objective's question the context's facts",
tool = "Speak",
prompt = """
Please answer the Objective's question using the relevant facts in your context.
If no facts are relevant just say that you don't know.
Don't state the Objective's question and only give the factual answer.
""",
))
main.connect("start", "fact_search")
main.connect("fact_search", "answer")
main.connect("answer", "end")
main.build() # Verify that the graph program is correct
# Let's look at it
print(main)
main.show(notebook=True)
from hybridagi.memory.integration.local import LocalProgramMemory
program_memory = LocalProgramMemory(index_name="knowledge_rag")
program_memory.update(main)
// @desc: The main program
CREATE
// Nodes declaration
(start:Control {id: "start"}),
(end:Control {id: "end"}),
(fact_search:Action {
id: "fact_search",
purpose: "Find relevant facts",
tool: "FactSearch",
prompt: "Please infer the similarity search query (only ONE item) based on the Objective's question"
}),
(answer:Action {
id: "answer",
purpose: "Answer the Objective's question the context's facts",
tool: "Speak",
prompt: "\\nPlease answer the Objective's question using the relevant facts in your context.\\nIf no facts are relevant just say that you don't know.\\nDon't state the Objective's question and only give the factual answer.\\n"
}),
// Structure declaration
(start)-[:NEXT]->(fact_search),
(fact_search)-[:NEXT]->(answer),
(answer)-[:NEXT]->(end)
Output
import dspy
import os
from hybridagi.core.datatypes import AgentState, Query
from hybridagi.modules.agents import GraphInterpreterAgent
from hybridagi.modules.agents.tools import SpeakTool, FactSearchTool
from hybridagi.modules.retrievers.integration.local import FAISSFactRetriever
agent_state = AgentState()
tools = [
SpeakTool(
agent_state = agent_state,
),
FactSearchTool(
retriever = FAISSFactRetriever(
fact_memory = fact_memory,
embeddings = embeddings,
distance = "cosine",
max_distance = 1.0,
k = 5,
reranker = None,
)
)
]
agent = GraphInterpreterAgent(
agent_state = agent_state,
program_memory = program_memory,
tools = tools,
)
# We can now setup the LLM using Ollama client from DSPy
lm = dspy.OpenAI(api_key = 'sk-')
dspy.configure(lm=lm)
# lm = dspy.OllamaLocal(model='mistral', max_tokens=1024, stop=["\\n\\n\\n"])
# dspy.configure(lm=lm)
result = agent(Query(query="In which movie Elijah Wood played?"))
print(result.final_answer)
--- Step 0 ---
Call Program: main
Program Purpose: In which movie Elijah Wood played?
--- Step 1 ---
Action Purpose: Find relevant facts
Action: {
"queries": [
"Elijah Wood",
"movie",
"played"
],
"facts": [
{
"fact": "(:Link {name:\\"<https://www.imdb.com/title/tt1375666/\\>"})-[:BELONGS_TO_CATEGORY]->(:Category {name:\\"Adventure\\"})"
},
{
"fact": "(:Link {name:\\"<https://www.imdb.com/title/tt0468569/\\>"})-[:BELONGS_TO_CATEGORY]->(:Category {name:\\"Drama\\"})"
},
{
"fact": "(:Link {name:\\"<https://www.imdb.com/title/tt0068646/\\>"})-[:BELONGS_TO_CATEGORY]->(:Category {name:\\"Drama\\"})"
},
{
"fact": "(:Link {name:\\"<https://www.imdb.com/title/tt0108052/\\>"})-[:BELONGS_TO_CATEGORY]->(:Category {name:\\"History\\"})"
},
{
"fact": "(:Link {name:\\"<https://www.imdb.com/title/tt0109830/\\>"})-[:HAS_TITLE]->(:Title {name:\\"Forrest Gump\\"})"
}
]
}
--- Step 2 ---
Action Purpose: Answer the Objective's question the context's facts
Action: {
"message": "Elijah Wood played in the movie \\"Forrest Gump\\"."
}
--- Step 3 ---
End Program: main
Elijah Wood played in the movie "Forrest Gump".
기존 Step by Step으로 결과를 내려면 많은 프롬프트 엔지니어링을 해줘도 불확실성이 있었는데 HybridAGI는 이를 명확한 행동과 프롬프트로 최적화하여 이에 드는 비용은 줄이고 성능은 향상시킨다.
[결론]Text to Knowledge graph에 대한 고찰
요즘 Text to knowledge graph에 대해 관심을 가지고 공부 중이다.
정확히는 어떤 도메인이 있으면 그 도메인에 맞게 정제되지않은 데이터를 그 도메인에 맞는 그래프로 재탄생시키는 것에 대해서 공부 중이다. 이러한 방식은 상당히 많은 것들을 고려해야하고 다음과 같은 Neuro-symbolic AI 관점에서 추론을 해야할 것이다.
뉴럴 AI는 신경망(neural network) 형태로 구축된 딥러닝 알고리즘을 활용한다. 심볼릭 AI와 달리 학습을 통해 사전에 정의되지 않은 패턴도 구분할 수 있고, 입력값에 다소 노이즈가 있어도 높은 확률로 정확한 출력값을 낼 수 있다. 하지만 입력값이 복잡해질수록 모델의 구조 또한 복잡해져, 내부 구조가 블랙박스화 되면서 해석이 불가능해질 위험도 안고 있다.
전통적인 방식인 심볼릭 AI는 사전에 입력한 규칙(rule)을 판단 기준으로 삼는 방법이다. 입력값의 특징에 대해 잘 알고 정확한 규칙을 설정할 수 있다면, 학습 데이터가 적거나 아예 없어도 정확한 출력값을 제공할 수 있다. 알고리즘이 작동하는 과정도 비교적 정확하게 파악할 수 있다.
[출처] Neuro-symbolic AI(뉴로-심볼릭) AI란?|작성자 TMISeoul
이를 구현하는 여러 방법이 떠오르지만 어떤 방법이 효과적일지는 미지수이다.
따라서 앞으로는 심도깊게 관련 연구를 찾아봐야겠다.
ps. "AI는 결국은 인간을 모방함으로써 완성되는 것인가" 라는 생각이 든다.
