AISmarteasy – 시맨틱 커널 개발하기 4 – 네이티브 함수
llm이 획기적인 발전을 했지만, 그렇다고 기존 개발이 다 없어지지는 않는다. llm이 아직 못하는 게 더 많다. 시맨틱 커널은 llm 연동해서 llm에게 지시하는 함수를 시맨틱 함수라고 하고, 기존에 개발 되었거나 기존과 같이 개발되는 함수를 네이티브 함수라고 한다.
물론 ai 애플리케이션은 llm 연동이 중요하니, 네이티브 함수는 llm이 잘 할 수 있는 환경을 만들도록 llm을 보조 하는 기능 정도를 추가적으로 개발해야 한다. 주객이 전도되면 안 된다.
llm은 언어 모델이라 점점 좋아지고는 있지만 복잡한 추론이나 계산은 아직 힘겨워 한다. 또한 사용자와 오랜 시간 주고 받은 내용들을 장기 기억하는 것을 어려워 하고, 현재 날짜나 시간을 알기도 어려워 한다.
기업의 경우, 자기들의 주 애플리케이션이 있고 여기에 ai를 덧 입히고자 하는 경우가 많은데 이들과 결합하는 부분이나 이미 유명한 웹 서비스와의 연동 부분에도 네이티브 함수가 필요하다.
여기서 주의해야 할 것은 네이티브 함수라고 한다고 기존 개발하고 같은 것으로 생각하면 안 된다. 네이티브 함수가 ai 애플리케이션에 존재하는 이유가 llm 보조, 즉 시맨틱 함수 보조라는 것을 강하게 새겨둬야 한다.
네이티브 함수를 만든다는 것은 기존 개발에 이런 부분을 반영해 주어야 한다는 것이다. 그렇다고 뭐 특별히 어려운 것을 요구하지는 않는다. llm이 언어 모델이니 함수와 주고 받는 내용이 자연어 텍스트라는 것을 기본으로 깔아두고, 함수라는 것을 생각해보면 어떤 부분이 변하고 추가적으로 필요할 지 생각할 수 있을 것이다.
두 수를 더하고 제곱근을 구하는 기능을 추가해 보자. Add와 Sqrt 함수
두 함수는 수학 계산하는 거니 MathSkill 플러그인으로 묶자.
Add와 Sqrt가 네이티브 함수이고 뭘 하는 것인지 알려줘야 한다. 함수를 관리하고 실행하는 입장에서 시맨틱 인지 네이티브 인지 구분할 필요는 없다. 그냥 모두 함수라는 것만 알려주면 된다.
시맨틱 커널에서는 커널의 컨텍스트를 함수 실행에서 공유해 주고 있고, input은 기본 제공 변수다. 시맨틱 커널의 모든 함수들은 매개변수를 등록하고 값을 설정하지 않아도 input 변수는 기본적으로 접근할 수 있다.
Sqrt의 경우 제곱근을 구할 숫자 하나만 있으면 되니, 매개변수 이름을 input으로 하고 추가적인 설명을 작성하지 않아도 된다. Add는 두 수를 더 하는 거니 하나는 input으로 받더라도 다른 하나가 정해져야 하고 input도 상대적인 의미를 갖기 때문에 설명도 작성해 주는 게 좋다.
네이티브 함수의 매개변수들과 리턴이 문자열이라는 것을 주의 깊게 보자.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
public class MathSkill { [SKFunction, Description("Take the square root of a number")] public string Sqrt(string input) { var result = Convert.ToDouble(input, CultureInfo.InvariantCulture); result = System.Math.Sqrt(result); return result.ToString(CultureInfo.InvariantCulture); } [SKFunction, Description("Add two numbers")] [SKParameter("input", "The first number to add")] [SKParameter("number", "The second number to add")] public string Add(SKContext context) { var result = Convert.ToDouble(context.Variables["input"], CultureInfo.InvariantCulture) + Convert.ToDouble(context.Variables["number"], CultureInfo.InvariantCulture); return result.ToString(CultureInfo.InvariantCulture); } } |
[설계 결정]
1. 시맨틱 함수와 같이 네이티브 함수도 plugin 폴더 하위에 native 폴더로 구분한다.
plugin
– semantic
– native
2. 플러그인은 클래스로, 네이티브 함수는 클래스 메소드로 작성한다.
예) MathSkill – Sqrt, Add
일반적인 개발이라면, Sqrt(634)와 같이 함수를 호출하는 코드를 작성했을 것이다. 그런 거는 이제 그만. llm 연동 ai 애플리케이션 이라면 “What is the square root of 634?” 이렇게 묻는 프롬프트를 작성해서 전달해서 처리할 수 있도록 해야 한다.
llm 연동 ai 애플리케이션에서 이를 처리하는 방법은 llm 의존도에 따라 두 가지 방법으로 나눌 수 있다. llm 의존도가 높은 방법은 목표를 프롬프트로 제시하고 llm이 어떤 함수들을 선택해서 어떤 절차로 처리 할지 결정하도록 하는 것이다. llm 의존도를 낮춘 방법은 프롬프트에서 의도와 인자를 파악하는 시맨틱 함수를 두고, 의도에 따라 결정된 함수를 호출 처리하는 네이티브 함수를 두는 것이다.
llm 의존도를 낮추는 방법은 개발자 손을 더 많이 탄다. llm 연동 ai 애플리케이션을 개발 한다면 개발자 손 보다는 llm에 의존하는 쪽으로 갈 수 있도록 하자. 개발자 손이 아니라 llm에 의존하는 방식으로 간다면 목표가 프롬프트로 전달되면, llm이 어떻게 할지 계획을 세우도록 하고, 그 계획을 받아 처리하는 방식으로 일반화된 개발을 할 것이다. 시맨틱 커널은 플래너를 제공해서 이걸 하도록 한다. llm이 이런 것을 하려면 목표 뿐만 아니라 이렇게 하라는 지시 또한 프롬프트로 전달되어야 한다. 이렇게 되려면 결국 플래너도 시맨틱 함수여야 한다. 시맨틱 커널에서 플래너 클래스는 시맨틱 함수 클래스를 상속 받고 있다.