Doc-string 관리
Agent를 LangGraph로 구현해서 사용하다 보면
run 함수나 tool 정의에 있어서 다음과 같은 Error 가 나온다
ValueError: Function must have a docstring if description not provided
해결방법은 생각보다 단순한데 그냥 해당 오류가 나오는 곳에 doc-string으로 description을 적어서
Agent에게 해당 함수를 설명해 주면된다
@tool("Second_tool", return_direct=True)
def Second_tool(param1: str, param2: int) -> str:
'''
이것은 나의 두번째 tool 입니다
'''
logger.info(f"MY First Tool")
근데 이거는 단순하게 구현을 했을 때는 문제가 없이 깔끔해 보일 수 있지만
Prompt가 길어질 수록 Prompt를 따로 관리하고 싶어지게 된다 (본인은 yaml로)
이에 따라 두 가지 경우가 나뉜다
- tool 에 대한 Description 관리
이거는 굉장히 단순하게 해결할 수 있다
위에 ValueError라 하고 뒤에 나오 듯이 doc-string을 적어주던가 description attribute를 추가해주면 된다
- a. description을 추가하는 방법
@tool("First_tool", return_direct=True, description=prompts["My_Agent"]["First_tool"])
def First_tool(param1: str, param2: int) -> str:
logger.info(f"MY First Tool")
- b. doc-string 을 직접 적어주는 방법
@tool("Second_tool", return_direct=True)
def Second_tool(param1: str, param2: int) -> str:
'''
이것은 나의 두번째 tool 입니다
'''
logger.info(f"MY First Tool")
- Agent Class 내부의 Description 관리
이 경우는 약간의 꼼수를 부리면 된다
나같은 경우는 Orchestration Agent가 각각 Agent의 run을 호출하는 다음과 같은 구조여서
class Orchestration_Agent:
def __init__(self):
self.name = 'Orchestration_Agent'
self.orch_llm = ChatOpenAI(
openai_api_base=base_url,
openai_api_key=api_key,
model="gpt-5.2",
temperature=0
)
self.agents = [Agent1().run, Agent2().run, My_Agent().run]
self.orch_agent = self.orch_llm.bind_tools(self.agents)
각 Agent에 구현한 run함수가 tool 방식을 채택하고 있다.
골치 아픈 것은 이 run 함수 자체가 tool이 아니기 때문 @tool 데코레이터를 쓰기에는 좀 껄끄러운 점도 있다
그러면 doc-string을 다이렉트로 쓰는 방법 밖에 없냐?
다음과 같이 꼼수로 init 생성자에 run 함수에 대한 doc string 을 덮어쓰기 시키는 방식을 하면 된다
class My_Agent:
def __init__(self):
self.name = 'My_Agent'
self.my_llm = ChatOpenAI(
openai_api_base=base_url,
openai_api_key=api_key,
model="gpt-5.2",
temperature=0
)
# ✅ run 함수의 docstring을 yaml description으로 설정
self.description = prompts["My_Agent"]["description"]
# run 메서드의 docstring을 동적으로 주입
# ✅ 클래스 함수 객체의 docstring 수정
My_Agent.run.__doc__ = self.description
#self.run.__doc__ = self.description
참고 : 만약 @tool을 사용하겠다고 하면
@tool("My_Agent_run", description=prompts["My_Agent"]["description"])
def run(self,state: State):
logger.info(f"[{self.name}]가 실행됩니다")
TypeError:'StructuredTool' object is not callable
이런 걸 볼 수 있다
즉, @tool 데코레이터가 붙는 순간 더이상 함수가 아니기 때문에
위에 Agent run을 list로 나열하고
이중에 뽑아서 쓰는 방식이 아닌
agent1 = Agent1().run
result = agent1.invoke({"state": state})
뭐 이런식으로 해야되서 귀찮아 진다...;;;
아래 같은 Error 가 나오면
AttributeError:attribute '__doc__' of 'method' objects is not writable
위에 구조를 잘 따랐는지 확인해보자
최종적으로는 다음과 같이 예시코드를 짜볼 수 있다
'''
Agent에 Doc-string을 yaml로 관리하는 방법
'''
from core.graph.state import State
import yaml
with open("config/prompt.yaml", "r", encoding="utf-8") as f:
prompts = yaml.safe_load(f)
# main에 사용한 logger 불러오기
import logging
logger = logging.getLogger("main")
'''
return_direct=False이면 도구의 결과가 모델 내부로 다시 들어가서 후처리나 추가 설명을 거친 뒤 사용자에게 전달.
return_direct=True이면 모델이 그 결과를 가공하지 않고 도구의 반환값을 그대로 사용자에게 보여줌.
'''
# tool은 class 밖에 있어야 한다
@tool("First_tool", return_direct=True, description=prompts["My_Agent"]["First_tool"])
def First_tool(param1: str, param2: int) -> str:
logger.info(f"MY First Tool")
@tool("Second_tool", return_direct=True)
def Second_tool(param1: str, param2: int) -> str:
'''
이것은 나의 두번째 tool 입니다
'''
logger.info(f"MY First Tool")
class My_Agent:
def __init__(self):
self.name = 'My_Agent'
self.my_llm = ChatOpenAI(
openai_api_base=base_url,
openai_api_key=api_key,
model="gpt-5.2",
temperature=0
)
# ✅ run 함수의 docstring을 yaml description으로 설정
self.description = prompts["My_Agent"]["description"]
# run 메서드의 docstring을 동적으로 주입
# ✅ 클래스 함수 객체의 docstring 수정
My_Agent.run.__doc__ = self.description
#self.run.__doc__ = self.description
def __str__(self):
return f"[{self.name}] {self.description}"
def run(self,state: State):
logger.info(f"[{self.name}]가 실행됩니다")
# 도구를 tools 리스트에 추가
self.tools = [production_stats,production_stats2]
self.my_agent = self.my_llm.bind_tools(self.tools)
# 도구를 모델에 바인딩: 모델에 도구를 바인딩하면, 도구를 사용하여 llm 답변을 생성할 수 있음
class Orchestration_Agent:
def __init__(self):
self.name = 'Orchestration_Agent'
self.orch_llm = ChatOpenAI(
openai_api_base=base_url,
openai_api_key=api_key,
model="gpt-5.2",
temperature=0
)
self.agents = [Agent1().run, Agent2().run, My_Agent().run]
self.agent_dict = {
"Doc-Agent": Agent1().run,
"Graph-Agent": Agent2().run,
"Trans-Agent": My_Agent().run,
}
self.orch_agent = self.orch_llm.bind_tools(self.agents)
def run(self,state: State):
agent = self.agent_dict.get(action)
if not agent:
continue
# logger.info(f"[Processing] {action} 실행")
# try:
if action == "Agent":
result = agent(state, factory_name)
# logger.info("search_result : ",result)
elif action == "Graph-Agent":
result = agent(state, state["search_result"]["processed_df"])
#
elif action == "Trans-Agent":
result = agent(state)
else:# 이거 나올 일 없긴 함
logger.info(f"please make this Agent : {action}",)
result = agent(state)
if result is not None:
state.update(result)
'AI Study > AI Agent' 카테고리의 다른 글
| Agent Tool Call 구현 및 Tool 호출에 따른 조건 추가하기 (0) | 2026.02.03 |
|---|---|
| [AI Agent] ollama 외부 연결 Setting(Container + local) (0) | 2025.10.30 |
| [AI Agent] ollama 모델 Open Web ui 연동(Docker) (0) | 2025.10.29 |
| Ollama를 이용한 환경 세팅 (0) | 2025.10.27 |
| [AI Agent] Langchain의 기초 (0) | 2025.10.23 |