본문 바로가기

Software

LLM을 앱에 연결해주는 microsoft의 Semantic Kernel

  Semantic Kernel 이란?

  • 앱에 AI 기능을 추가하는 개발자에게 유연성을 제공하기 위한 microsoft의 오픈 소스
  • C#, Python 같은 기존 프로그래밍 언어와 LLM AI를 결합시켜주는 경량 SDK
  • 오픈 소스 프레임워크로 예제 앱과 노트북이 함께 제공됨
  • 시맨틱 커널 설계의 핵심은 SkillPlanner
    • Planner 는 사용자의 요청을 받아 필요한 스킬, 메모리, 커넥터로 변환하여 복잡한 작업을 용이하게 함
    • Skill 은 어떤 기능을 하는 역할을 하는 함수나 모듈의 집합
  • OpenAI의 모델과 Azure OpenAI Service 지원

  자주 사용되는 용어

  • Semantic Kernel (SK)
    • 사용자의 ASK를 이행하는 오케스트레이터
  • Ask
    • 사용자가 목표 달성을 위해 시맨틱 커널에 요청하는 내용
      • “우리는 SK에 Ask를 한다” 고 표현
  • Skill
    • SK에서 사용할 수 있는 도메인별 기능 그룹
  • Function
    • 시맨틱 스킬에서 사용할 수 있는 네이티브 코드
  • Semantic Function
    • SK의 프롬프트 템플릿 언어를 사용하여 텍스트 파일 skprompt.txt 에 자연어로 표현됨
  • Memory
    • 임베딩 색인

결국 커널은 사용자가 여러 함수를 단일 파이프라인으로 구성하도록 돕는다.

 

 

  SK Planner

플래너는 유저의 ASK가 들어왔을 때 이를 Skill, Memory, Connector 로 분할하고 목표를 달성할 수 있도록 계획을 세운다.

 

 

  Skills

  • 커널에서 단일 기능 또는 스킬과 관련된 기능 그룹으로 사용할 수 있는 전문 영역을 의미
    • 쉽게 말해, 어떠한 역할을 하는 함수나 모듈의 집합
  • 함수는 스킬의 기본 구성 요소
    1. semantic code - LLM에 대한 프롬프트를 의미 (=시맨틱 함수 라고도 함)
    2. native computer code - 일반 컴퓨터 코드 (=네이티브 함수 라고도 함)
    3. navtive 컴퓨터 코드를 사용할 때 LLM AI 프롬프트를 호출 → 하이브리드 형식도 가능
  • 스킬은 함수가 들어있는 컨테이너
  • 시맨틱 스킬은 시맨틱 함수들을 포함하는 폴더라고 생각하면 됨
  • 각 함수에는 skprompt.txtconfig.json 파일이 존재한다.
SkillName (directory name)
│
└─── Function1Name (directory name)
			│
			└─── skprompt.txt
			└─── config.json
│   
└─── Function2Name (directory name)
			│
			└─── skprompt.txt
			└─── config.json
  • 네이티브 스킬 은 Azure Function에서 영감을 받은 것으로, 아래와 같이 개별 네이티브 스킬 파일로 존재한다.
MyAppSource
│
└───MySkillsDirectory
    │
    └─── MySemanticSkill (a directory)
    |   │
    |   └─── MyFirstSemanticFunction (a directory)
    |   └─── MyOtherSemanticFunction (a directory)
    │
    └─── MyNativeSkill.cs (a file)
    └─── MyOtherNativeSkill.cs (a file)
  • 해당 레포에서 스킬은 세 곳 중 한 곳에 저장 (이곳)
    1. Core Skills: 커널에서 언제든지 사용할 수 있는 스킬로, 시간, 텍스트, 파일, http 요청, 플래너 작업과 같은 몇 가지 표준 기능을 구현
    2. Semantic Skills: 사용자가 선택한 디렉터리에서 관리
    3. Native Skills: 사용자가 선택한 디렉터리에서 관리

 

  Python에서 시맨틱 커널 사용하기

파이썬 버전에서 시맨틱 커널을 실행할 경우 아래와 같이 수행한다.

  1. python -m pip install semantic-kernel
  2. Open AI API 키 또는 Azure Open AI 서비스 키를 .env 파일에 넣는다.
  3. 이곳의 프롬프트를 파일로 생성하고 실행한다.

아래는 간단한 예시이다.

import semantic_kernel as sk
from semantic_kernel.ai.open_ai import OpenAITextCompletion, AzureTextCompletion

kernel = sk.create_kernel()

# Prepare OpenAI backend using credentials stored in the `.env` file
api_key, org_id = sk.openai_settings_from_dot_env()
kernel.config.add_text_backend("dv", OpenAITextCompletion("text-davinci-003", api_key, org_id))

# Alternative using Azure:
# deployment, api_key, endpoint = sk.azure_openai_settings_from_dot_env()
# kernel.config.add_text_backend("dv", AzureTextCompletion(deployment, endpoint, api_key))

# Wrap your prompt in a function
prompt = kernel.create_semantic_function("""
1) A robot may not injure a human being or, through inaction,
allow a human being to come to harm.

2) A robot must obey orders given it by human beings except where
such orders would conflict with the First Law.

3) A robot must protect its own existence as long as such protection
does not conflict with the First or Second Law.

Give me the TLDR in exactly 5 words.""")

# Run your prompt
print(prompt()) # => Robots must not harm humans.
  1. 커널 생성
  2. 어떤 모델을 사용할지에 대한 구성 추가
  3. 프롬프트를 랩핑하여 시맨틱 함수 생성
  4. 프롬프트 실행

 

  SK의 Prompt Template 문법

sk에서는 프롬프트 템플릿의 문법을 정의하고 있는데, 해당 문법으로 아래 세 가지 기본 기능을 제공한다.

  1. 변수 포함
  2. 외부 함수 호출
  3. 함수에 매개변수 전달

프롬프트에 중괄호 {{...}} 를 사용하여 표현식을 포함시키면, 시맨틱 커널은 템플릿을 파싱하고 그 뒤에 있는 로직을 수행시키게 된다.

이때 이중 중괄호를 실제로 프롬프트에 포함하고 싶은 경우 {{"{{"}}{{"}}"}} 와 같이 따옴표로 묵인 문자열 값을 사용하도록 한다.

 

Variables

$변수명 형식으로 변수를 포함시킬 수 있다.

Hello {{$name}}, welcome to Semantic Kernel!

Function calls

모듈명.함수명 형식으로 회부 함수를 호출하고 그 결과를 프롬프트 텍스트에 포함시킬 수 있다.

# 기본 형태
The weather today is {{weather.getForecast}}.

# 함수에 인자를 전달해야하는 경우

# 1. city 변수를 사용할 경우
The weather today in {{$city}} is {{weather.getForecast $city}}.

# 2. 프롬프트 템플릿에 하드코딩된 "Schio" 위치값을 사용할 경우
The weather today in Schio is {{weather.getForecast "Schio"}}.

 

  사용법

0. 커널 생성하기

import semantic_kernel as sk

# 단순히 인스턴스를 생성하거나
kernel_1 = sk.Kernel()

# 커스텀 로거를 넣어 생성하거나
my_logger = sk.NullLogger()
kernel_2 = sk.Kernel(log=my_logger)

# 커스텀 설정을 넣어 생성할 수 있다. 
my_config = sk.KernelConfig()
kernel_2 = sk.Kernel(config=my_config)

AI 요청을 위해 커널을 사용하려는 경우 AI 모델에 대한 설정들을 추가해주어야 한다.

kernel.config.add_text_backend(               # We are adding a text backend
    "OpenAI_davinci",                         # The alias we can use in prompt templates' config.json
    OpenAITextCompletion(
        "text-davinci-003",                   # OpenAI Model Name
        "...your OpenAI API Key...",          # OpenAI API key
        "...your OpenAI Org ID..."            # *optional* OpenAI Organization ID
    )

 

1-1. 파일로부터 시맨틱 스킬을 로드하고 실행하기

import semantic_kernel as sk
from semantic_kernel.ai.open_ai import AzureTextCompletion, OpenAITextCompletion

# 커널을 생성하고 백엔드 설정을 추가한다.
kernel = sk.Kernel()

api_key, org_id = sk.openai_settings_from_dot_env()
kernel.config.add_text_backend("dv", OpenAITextCompletion("text-davinci-003", api_key, org_id))

# 스킬 임포트
skills_directory = "../../skills"

funFunctions = kernel.import_semantic_skill_from_directory(skills_directory, "FunSkill")

jokeFunction = funFunctions["Joke"]

이때 사용된 스킬은 아래와 같이 정의되어있다.

semantic-kernel/samples/skills/FunSkill/Joke/config.json

{
  "schema": 1,
  "description": "Generate a funny joke",
  "type": "completion",
  "completion": {
    "max_tokens": 1000,
    "temperature": 0.9,
    "top_p": 0.0,
    "presence_penalty": 0.0,
    "frequency_penalty": 0.0
  },
  "input": {
    "parameters": [
      {
        "name": "input",
        "description": "Joke subject",
        "defaultValue": ""
      }
    ]
  }
}

semantic-kernel/samples/skills/FunSkill/Joke/skprompt.txt

WRITE EXACTLY ONE JOKE or HUMOROUS STORY ABOUT THE TOPIC BELOW

JOKE MUST BE:
- G RATED
- WORKPLACE/FAMILY SAFE
NO SEXISM, RACISM OR OTHER BIAS/BIGOTRY

BE CREATIVE AND FUNNY. I WANT TO LAUGH.
{{$style}}
+++++

{{$input}}
+++++

 

 

1-2. 인라인으로 시맨틱 함수 실행하기

또는 아래와 같이 SK 템플릿 언어를 사용하여 코드 내에서 프롬프트 템플릿을 작성할 수도 있다.

sk_prompt = """
{{$input}}

Give me the TLDR in 5 words.
"""

text = """
    1) A robot may not injure a human being or, through inaction,
    allow a human being to come to harm.

    2) A robot must obey orders given it by human beings except where
    such orders would conflict with the First Law.

    3) A robot must protect its own existence as long as such protection
    does not conflict with the First or Second Law.
"""

tldr_function = kernel.create_semantic_function(sk_prompt, max_tokens=200, temperature=0, top_p=0.5)

summary = tldr_function(text)

print(f"Output: {summary}") # Output: Robots must not harm humans.

 

 

1-3. 컨텍스트 변수를 사용하여 채팅 환경 생성하기

  • 요청과 함께 컨텍스트를 보내고 업데이트하여 간단한 채팅 봇을 구축하는 예시
  • 컨텍스트는 로컬(즉, 컴퓨터의 RAM)이며 이 주피터 세션의 수명 이후에는 지속되지 않음
  • 향후 예제에서는 애플리케이션에 컨텍스트를 가져올 수 있도록 디스크에서 컨텍스트를 유지하는 방법을 보여줌
  • 이 채팅 시나리오에서는 사용자가 봇과 대화를 주고받을 때 컨텍스트에 대화 내역이 채워짐
  • 커널을 새로 실행할 때마다 컨텍스트는 AI에 변수의 콘텐츠를 제공할 수 있음

1) 프롬프트 생성

sk_prompt = """
ChatBot can have a conversation with you about any topic.
It can give explicit instructions or say 'I don't know' if it does not have an answer.

{{$history}}
User: {{$user_input}}
ChatBot: """

2) 시맨틱 함수 등록

chat_function = kernel.create_semantic_function(sk_prompt, "ChatBot", max_tokens=2000, temperature=0.7, top_p=0.5)

3) 컨텍스트 생성

context = sk.ContextVariables()
context["history"] = ""

4) 챗봇의 응답을 받기

context["user_input"] = "Hi, I'm looking for book suggestions"
bot_answer = await chat_function.invoke_with_vars_async(input=context)
print(bot_answer)

5) 챗봇의 응답을 히스토리에 업데이트

context["history"] += f"\nUser: {context['user_input']}\nChatBot: {bot_answer}\n"
print(context["history"])

위의 과정을 하나의 함수로 구현하면 아래와같다.

async def chat(input_text: str) -> None:
    # Save new message in the context variables
    print(f"User: {input_text}")
    context["user_input"] = input_text

    # Process the user message and get an answer
    answer = await chat_function.invoke_with_vars_async(context)

    # Show the response
    print(f"ChatBot: {answer}")

    # Append the new interaction to the chat history
    context["history"] += f"\nUser: {input_text}\nChatBot: {answer}\n"

실행 예시

>>> await chat("I love history and philosophy, I'd like to learn something new about Greece, any suggestion?")
>>>
User: I love history and philosophy, I'd like to learn something new about Greece, any suggestion?
ChatBot:  I would recommend reading The Histories by Herodotus. It is a great source of information about ancient Greece and its culture.

>>> await chat("that sounds interesting, what is it about?")
>>>
User: that sounds interesting, what is it about?
ChatBot:  The Histories by Herodotus is an account of the wars between the Greeks and the Persians in the 5th century BC. It is considered to be the first work of history in Western literature and provides an insight into the cultures of the time.

>>> await chat("if I read that book, what exactly will I learn about Greece history?")
>>>
User: if I read that book, what exactly will I learn about Greece history?
ChatBot:  The Histories by Herodotus provides an in-depth look at the wars between the Greeks and the Persians in the 5th century BC. It also provides an insight into the culture and beliefs of the ancient Greeks, including their mythology, religion, and customs.

>>> await chat("could you list some more books I could read about this topic?")
>>>
User: could you list some more books I could read about this topic?
ChatBot:  Sure! Other books you could read about ancient Greece include Thucydides' History of the Peloponnesian War, Plato's Republic, and Aristotle's Politics. You could also read Homer's Iliad and Odyssey for a more detailed look at Greek mythology.

 

  Reference

 

Hello, Semantic Kernel! | Semantic Kernel

Semantic Kernel (SK) is a lightweight SDK that lets you mix conventional programming languages, like C# and Python, with the latest in LLM AI "prompts" with prompt templating, chaining, and planning capabilities.

devblogs.microsoft.com

 

GitHub - microsoft/semantic-kernel: Integrate cutting-edge LLM technology quickly and easily into your apps

Integrate cutting-edge LLM technology quickly and easily into your apps - GitHub - microsoft/semantic-kernel: Integrate cutting-edge LLM technology quickly and easily into your apps

github.com