티스토리 뷰

인공지능

[LLM] Flowise 사용법 & LLM 프롬프트 엔지니어링 예시(Getting Started with Flowise & Prompt Engineering Examples for LLMs)

망나니개발자 2025. 6. 3. 10:00
반응형

 

 

1. Flowise에 대하여 & LLM 연동 준비하기


[ Flowise에 대하여 ]

Flowise란 시각적인 인터페이스를 제공하는 오픈 소스 LLM(대형 언어 모델) 워크플로 빌더로, 코드를 작성하지 않고도 다양한 LLM 기반 애플리케이션을 쉽게 구성하고 배포할 수 있도록 설계되어 있다.

 

 

예를 들어 우리가 애플리케이션에 LLM을 연동하여 계산기를 만드는 상황이라고 하자. 대부분의 애플리케이션은 연동을 위해 HTTP 프로토콜과 JSON 형태의 자료구조를 사용할 것인데, LLM의 응답은 다음과 같이 대화형인 경우가 많다.

 

 

서비스에 JSON 형태로 응답하려면, 위와 같은 응답 형식이 아닌, Key-Value 형태로의 응답 전환 등이 필요한데, Flowise는 이렇듯 서비스에 LLM을 연동하기 위해 필요한 컴포넌트들을 연동하여 원하는 결과를 얻을 수 있도록 한다.

그 외에도 여러 입력 데이터들을 연결하고, 가공하여 원하는 LLM 흐름을 개발할 수 있는 기능을 제공한다. 이번에는 다음과 같은 내용을 LLM에게 전달하여, 에러 발생 원인을 분석해주는 역할을 LLM Flow를 Flowise로 개발해보도록 하자.

httpMethod: POST,
requestUrl: /pet/{petId}/uploadImage,
cause: com.mangkyu.PetRepository$PetNotFoundException: cannot find pet
	at com.mangkyu.PetRepository.findById(PetRepository.java:10)
	at com.mangkyu.PetRepository$$SpringCGLIB$$0.findById(<generated>)
	at com.mangkyu.PetService.uploadImage(PetService.java:17)
	at com.mangkyu.PetController.uploadImage(PetController.java:19)

 

 

최종적으로 우리가 얻게 될 응답은 다음과 같은 형태가 될 것이다. 이를 위해 LLM Chain 구성을 API 문서 찾기 그리고 이를 바탕으로 한 에러 분석 2가지 단계로 나누어 구현해보도록 하자.

 

 

 

 

[ LLM 모델의 API Key 발급받기 ]

GroqChat API 연동하기

Groq은 무료로 API 연동을 지원하는 LLM 모델 중 하나이다. 다음의 페이지에서 Flowise와의 연동을 위한 API Key 발급을 받을 수 있다.

 

 

 

OpenAI(ChatGPT) API 연동하기

한국인들에게 특히나 애용되는 OpenAI의 ChatGPT는 무료로 API 연동을 지원하지 않는다. 따라서 별도의 credit 충전이 필요한데, 테스트 결과 OpenAI의 응답 성능이 가장 좋았기 때문에, 유료 버전을 사용중이라면 다음의 페이지에서 API Key를 발급받아 사용해주도록 하자.

 

 

이제 준비는 끝났다. 에러 분석을 LLM Chain을 구성하기 위해, 먼저 API 문서 조회 Flow 그리고 이를 바탕으로 한 에러 분석 Flow 2가지 단계로 나누어 구현해보도록 하자.

 

 

 

 

2. API 정보 조회를 위한 LLM Chain 구성하기


[ API 정보 조회를 위한 LLM Chain 구성하기 ]

API Loader는 외부 API를 통해 문서를 제공하는 방식으로 LLM 파이프라인에 활용할 수 있게 하는 노드이다. Json 파일 읽기, 동적 API 호출 등 다양한 방식으로 등록 가능하다. 이번 작업에서는 Swagger에서 제공하주는 PetStore Swagger Json API를 LLM에게 API 스펙 문서로써 제공해줄 것이다. Flowise에서 new flow를 생성해 새로운 canvas를 하나 생성하고, + 버튼을 눌러 API Loader를 다음과 같이 추가해주도록 하자. PetStore Swager Json API의 경우 GET 요청으로 https://petstore.swagger.io/v2/swagger.json 에 요청을 보내면, API 스펙 문서를 제공해주고 있기 때문에 다음과 같이 작성해주었다.
만약 정적인 데이터 파일을 제공하는 방식으로 LLM 파이프라인에 활용하고 있다면 API Loader가 아닌 Document Store를 활용하면 된다.

 

 

 

[ ChatModel 구성하기 ]

그 다음은 우리가 질의한 프롬프트 내용을 처리할 LLM 모델을 구성하는 것이다. 이번에는 무료 모델 Groq을 이용할 것이므로, Groq을 검색해서 다음과 같이 추가해주면 된다. 이때 Connect Credential에서 new를 눌러서 이전에 발급 받았던 API Key를 Credential로 등록하고 선택해주면 된다.

 

 

여기서 중요한 Temperature 속성은 0부터 1 사이의 값으로, 높을수록 창의적인 대답을, 낮을수록 정답을 제공한다. 이번에 만들고자 하는 에러 분석 플로우의 경우에는 주어진 정답을 찾는 상황이므로, 낮은 값을 선택하는 것이 유리하다. 따라서 0.2 정도로 설정하여 어느 정도 정답을 찾는 정도로 답변을 제공받도록 하자.

 

 

 

[ 프롬프트 구성하고 템플릿 생성하기 ]

이번 프롬프트는 주어진 API 스펙 문서에서 매칭되는 부분을 찾도록 하는 프롬프트이다. 간단한 작업인 만큼 별도의 예시 데이터 등을 프롬프트로 제공하지는 않았으며, 활용할 프롬프트는 다음과 같다. 관련 내용을 한번 읽고, 우리가 하고자 하는 작업을 LLM에게 어떻게 위임하는지 이해해주도록 하자.

# 스펙 문서
{spec}

# 역할(Role)
당신은 주어진 API 스펙 문서를 분석하는 스펙 분석 전문가입니다.

# 목표(Goal)
입력으로 주어지는 requestUrl과 httpMethod를 바탕으로, 해당하는 내용에 대응하는 내용을 찾습니다.


# 가이드라인(Guidelines)
주어진 스펙 문서에서 requestUrl과 Http Method를 바탕으로 매칭되는 API를 찾습니다. spec에서 주어진 API를 찾는 방법은 다음과 같습니다.
1. 주어진 spec에서 고정값 paths를 key로 갖는 부분을 찾음
2. 그 하위에서 사용자 입력값 requestUrl를 key로 갖는 부분을 찾음
3. 그 하위에서 사용자 입력값 소문자의 httpMethod를 key로 갖는 부분을 찾음


# 입력 형식(Input Format)
입력 데이터는 다음과 같이 구성되며, 각각은 다음을 의미합니다.
httpMethod: HTTP 메서드
requestUrl: 요청 URL
spec: API 스펙 문서


# 유의 사항(Cautions)
제공된 문서에서 requestUrl과 httpMethod에 매칭되는 API 스펙에서 summary를 찾은 값으로 반환하고, 찾지 못할 경우에는 공백으로 제공합니다.


# 출력 형식(Output Format)
httpMethod: 요청 받은 httpMethod 그대로
requestUrl: 요청받은 requestUrl 그대로
summary: 찾은 API 요청의 summary 부분 그대로, 없으면 공백으로 제공함
cause: 입력받은 cause 그대로

 

 

가장 상단에는 {spec}으로 스펙 문서를 제공해주고 있다. spec은 우리가 앞서 API Loader로 제공한 내용을 변수명 spec으로 설정할테니, 이를 LLM에게 활용하도록 한 것이다. 뒤에서 API Loader로 설정한 내용을 spec 변수로 설정할 것이다.

이어서 해당 프롬프트를 처리하는 노드를 추가해주어야 하는데, 해당 노드는 Chat Prompt Template이다. 이를 추가하고, System Message에는 위의 프롬프트를, Human Message에는 {question}을 추가해주도록 하자.

 

 

{question} 역시, 우리의 요청 메시지를 question이라는 변수명으로 제공해줄테니 치환해서 사용하라는 의미이다. 예를 들어 다음과 같이 "25 * 30의 결과를 알려줘" 라는 내용을 question이라는 변수로 제공해준다는 의미인 것이다.

 

 

그러면 이제 question과 spec이라는 변수를 설정해주어야 한다. 이는 위의 Chat Prompt Template에서 Format Prompt Values를 눌러서 다음과 같이 설정해주면 변수 설정이 완료된 것이다.

 

 

 

[ Structured Output Parser 구성하기 ]

이제 대화형으로 생성된 LLM(Large Language Model)의 응답을 특정 포맷(구조화된 형식)으로 변경해주는 노드를 추가할 차례이다. 이번에는 출력 결과를 key-value 형태로 갖는 Json 형태로 응답이 제공되도록 할 것이므로, Structured Output Parser 노드를 추가하고, 위의 프롬프트 출력 결과에 해당하는 내용들을 다음과 같이 추가해주도록 하자. 아래의 JSON Structure에는 잘려서 안나와있지만, 제공해준 프롬프트대로 cause Property까지 모두 추가해주어야 한다.

 

 

 

[ LLM Chain 구성하기 ]

이제 마지막으로, 위의 주어진 노드들을 연결하여 하나의 이어진 플로우를 구성할 차례이다. 이를 위해 사용되는 노드는 LLM Chain으로, 하나 이상의 LLM(대규모 언어 모델)과 관련 노드들을 연결해 체인을 구성해주는데, 사용자의 입력을 처리하고 원하는 출력을 만들어내는 핵심 파이프라인이라고 볼 수 있다. 해당 플로우를 다음과 같이 최종 구성해주도록 하자.

 

 

 

여기서 LLM Chain의 Output으로는 크게 2가지가 존재하는데, 각각 다음과 같다.

  • LLM Chain: 전체 체인을 실행한 프롬프트 결과
  • Output Prediction: 최종적으로 flowise를 통해 생성되는 응답

 

 

우선, 프롬프트 결과 확인을 위해 Output을 LLM Chain으로 해두었다. 옆의 대화창에서 다음의 예시 메시지를 보내보도록 하자.

httpMethod: POST,
requestUrl: /pet/{petId}/uploadImage,
cause: com.mangkyu.PetRepository$PetNotFoundException: cannot find pet
	at com.mangkyu.PetRepository.findById(PetRepository.java:10)
	at com.mangkyu.PetRepository$$SpringCGLIB$$0.findById(<generated>)
	at com.mangkyu.PetService.uploadImage(PetService.java:17)
	at com.mangkyu.PetController.uploadImage(PetController.java:19)

 

 

 

그러면 메시지가 question 변수로 전달되게 되어, 다음과 같은 LLM Chain의 출력 결과를 확인할 수 있다. 그리고 summary는 앞선 API Loader를 통해 제공된 부분 중에서 requestUrl과 httpMethod를 바탕으로 찾은 내용을 전달해주었음을 확인할 수 있다.

 

 

지금까지 구성한 Flow는 다음의 파일에 정리되어 있으니, 필요하다면 해당 Flow를 Load하여 사용하도록 하자.

documentation_flow.json
0.03MB

 

 

 

 

참고로 해당 summary를 에러 분석에 제공하고자 하는 이유는, 현재 클라이언트가 수행하는 작업이 무엇인지에 대한 메타데이터를 제공하기 위함이다. 그러면 이어서 해당 정보를 다시 LLM에게 제공하고, 에러 발생 원인과 수정 방향 등에 대한 제공을 해주는 에러 분석LLM Chain을 구성해보도록 하자.

 

 

 

 

3. 에러 분석을 위한 LLM Chain 구성하기


[ 기존 LLM Chain의 응답 변경하기 ]

먼저 위에서 구성한 LLM Chain의 결과가 다른 LLM Chain으로 이어지도록, Output을 Output Prediction으로 변경해주도록 하자.

 

 

 

[ Prompt Template 작성하기 ]

에러 분석을 위한 프롬프트를 작성할 때에는 다음과 같은 내용에 주의하여 작성되었다.

  • 고급 BE 개발자와 주니어 FE 및 PM으로 역할을 지정하여 서술하는 내용을 쉽게 이해 가능하도록 함
  • API 스펙을 요청의 메타데이터로 제공하여 도메인 언어로 에러가 발생한 상황을 소통할 수 있도록 함
  • API 스펙이 제공되지 않은 경우에 대비해, 클래스 및 메서드 정보를 바탕으로 추론을 보완하도록 함
  • 예시를 제공하고, 추론의 이유를 서술하도록 하여 정확도를 높일 수 있도록 함

 

 

이렇게 작성된 프롬프트의 내용은 다음과 같다.

# 요청 정보
요청 URL: {requestUrl}
요청 HttpMethod: {httpMethod}
요청중인 기능: {summary}
발생한 에러: {cause}


# 역할(Role)
당신은 HTTP를 기반으로 통신하는 환경에서 Java/Kotlin 개발 언어와 SpringBoot 프레임워크의 JVM 환경 기반 개발  경험을 7년 이상 보유한 서버 개발의 전문가입니다.

# 목표(Goal)
입력으로 주어지는 요청 URL과 요청 HttpMethod 그리고 에러의 StackTrace를 바탕으로, 해당 에러가 해당 서비스를 이용하는 사용자의 입장에서 어떤 상황에서 발생했고, 왜 발생했는지를 분석합니다. 상대방은 이제 막 개발을 시작한 1년차 FE 개발자와 새롭게 팀에 합류한 PM 기획자 둘이기 때문에, 최대한 이해하기 쉽게 내용을 설명해주어야 합니다.
어떤 요청을 보낸 상황에서 문제가 발생했고, 에러가 생긴 원인은 무엇이고, 어떻게 해결할 수 있을지를 분석하여 이를 제공해주어야 합니다.


# 가이드라인(Guidelines)
해당 요청이 어떠한 요청인지는 API 관련 문서를 apiLoader를 통해 제공받을 것이므로, apiLoader에서 requestUrl과 Http Method를 바탕으로 매칭되는 정보를 찾고, 해당 부분에서 "summary"를 참조하면 됩니다. "summary"가 없는 경우에는 제공받은 StackTrace를 바탕으로 호출된 Controller 클래스의 이름과 메소드와 requestUrl + Http Method를 바탕으로 추론하면 됩니다.
apiLoader에서 summary를 찾는 방법은, 해당 정보가 JSON 포맷이기 때문에, "paths"를 먼저 key로 매칭되는 부분을 찾고, 그 중에서 "requestUrl"을 Key로 갖는 부분을 찾습니다. 이후에 "HttpMethod"를 키로 갖는 부분을 찾으면 됩니다.
에러가 발생한 원인은 입력으로 한 줄의 핵심 메시지인 errorMessage와 StackTrace를 제공받을 것이기 때문에 해당 내용을 분석하여 reason을 작성함으로써 PM이 왜 문제가 발생했는지를 인지할 수 있도록 하고, guide를 작성함으로써 FE 개발자가 어떻게 고치면 좋을지 제안해주면 됩니다.

# 입력 형식(Input Format)
입력 데이터는 다음과 같이 구성되며, 각각은 다음을 의미합니다.
httpMethod: HTTP 요청 메서드
requestUrl: HTTP 요청 URL
errorMessage: 에러가 발생한 핵심 메시지
cause: 에러가 발생한 StackTrace


# 입력 예시(Input Example)
1번 예시
httpMethod: "get"
requestUrl: "/apis/1.0/image-cards/{id}"
cause:  "im.toss.teens.imagecard.adapter.persistence.ImageCardRepository$ImageCardNotFound: 존재하지 않는 이미지카드에요.
at im.toss.teens.imagecard.adapter.persistence.ImageCardRepository$ImageCardNotFound.<clinit>(ImageCardRepository.kt)
at im.toss.teens.imagecard.adapter.persistence.ImageCardRepository.findByIdOrThrow$lambda$0(ImageCardRepository.kt:27)
at im.toss.teens.imagecard.adapter.persistence.ImageCardRepository.findByIdOrThrow(ImageCardRepository.kt:27)
at im.toss.teens.home.adapter.outbound.persistence.config.RoutingDataSourceInterceptor.annotationRoutingDataSourceAnnotation(RoutingDataSourceInterceptor.kt:19)
at im.toss.teens.imagecard.adapter.persistence.ImageCardRepository$$SpringCGLIB$$0.findByIdOrThrow(<generated>)
at im.toss.teens.imagecard.application.services.GetImageCardService.execute(GetImageCardService.kt:34)
at im.toss.teens.api.controller.imagecard.web.ImageCardController.getImageCard(ImageCardController.kt:47)
at im.toss.teens.api.controller.imagecard.web.ImageCardController$$SpringCGLIB$$0.getImageCard(<generated>)
"

2번 예시
httpMethod: "get"
requestUrl: "/apis/1.0/card/images-cards"
cause:  "java.lang.IndexOutOfBoundsException: toIndex (4) is greater than size (0).
	at im.toss.teens.invitation.adapter.cache.redis.UserShareKeyEncrypter.decrypt(UserShareKeyEncrypter.kt:35)
	at im.toss.teens.api.controller.imagecard.web.ImageCardController.getImageCard(ImageCardController.kt:29)
	at im.toss.teens.api.controller.imagecard.web.ImageCardController$$SpringCGLIB$$0.getImageCard(<generated>)
	at java.base/java.lang.Thread.run(Thread.java:840)
"



# 유의 사항(Cautions)

제공된 문서에서 API URL과 Http Method를 바탕으로 매칭되는 정보가 없는 경우에는 확인되는 API 정보가 없다는 의미로 응답을 주면 됩니다.

# 출력 형식(Output Format)

"action": "처리 요청을 보냈던 행동"
"reason": "에러가 발생한 이유"
"guide": "에러 수정에 대한 가이드"
"inference": "그렇게 action과 reason, guide를 추론한 이유"
"apiSummary": "api 문서에서 찾은 summary"

# 출력 예시(Output Example)

1번 예시
"action": "이미지 카드 단건 조회 시에 에러가 발생했습니다."
"reason": "존재하지 않는 이미지 카드를 조회하려고 시도했기 때문입니다."
"guide": "존재하는 이미지 카드 ID를 전달해주세요."
"inference": "전달받은 requestUrl과 httpMethod를 바탕으로 apiLoader에서 이미지 카드 단건 조회라는 것을 파악하였고, StackTrace의 일정 부분인 ImageCardNotFound: 존재하지 않는 이미지 카드에요.을 참고하여 잘못된 ID가 전달되었다고 추론했습니다."
"apiSummary": "이미지 카드 단건 조회"

2번 예시
"action": "친구 목록 조회 시에 에러가 발생했습니다.",
"reason": "파라미터로 존재하는 shareCode 값이 누락되었기 때문입니다.",
"guide": "누락된 shareCode 파라미터를 전달해주세요."
"inference": "전달받은 requestUrl과 httpMethod를 바탕으로 API Loader에서 친구 목록 조회라는 것을 파악하였고, StackTrace의 일정 부분인 Required request parameter 'shareCode' for method parameter type String is not present을 참고하여 shareCode가 누락되었다고 추론했습니다."
"apiSummary": "shareCode로 친구 목록 조회"

3번 예시
"action": "암호화된 사용자 키로 사용자 정보 조회 시에 에러가 발생했습니다.",
"reason": "복호화에 실패했기 때문입니다.",
"guide": "올바른 값을 전달해주세요."
"inference": "API Loader에서 원하는 API를 찾지 못하여 전달받은 requestUrl과 httpMethod 그리고 StackTrace를 통해 현재 수행되는 작업이 암호화된 사용자 키로 사용자 조회라는 것을 추론하였고, StackTrace의 일정 부분인 im.toss.teens.invitation.adapter.cache.redis.UserShareKeyEncrypter.decrypt를 호출하는 과정에서 에러가 발생한 것을 참고하여 잘못된 키가 전달되었다고 추론했습니다."
"apiSummary": "암호화된 사용자 키로 사용자 정보 조회"

 

 

이전에 사용된 Chat Prompt Template과 달리 PromptTemplate은 ChatPromptTemplate의 간소화된 버전이라고 볼 수 있다. 해당 내용을 이전 LLM Chain의 결과와 연결해주어야 한다. 그리고 마찬가지로 이전 응답의 결과를 별수로 설정하여 현재의 템플릿에 연결해줄 필요가 있다.

 

 

 

[ LLM Chain 구성하기 ]

이제 기존에 만들어뒀던 LLM 모델과 새롭게 추가한 노드를 연결하여, 최종적인 Flow를 구성할 차례이다. 이를 구성한 내용을 정리하면 다음과 같다. Language Model의 경우 이전에 구성해둔 ChatModel을 그대로 연결해주면 된다.

 

 

 

 

[ Structured Output Parser 구성하기 ]

마지막으로 이전에 했던 것처럼 대화형으로 생성된 LLM(Large Language Model)의 응답을 특정 포맷(구조화된 형식)으로 변경해줄 차례이다. 동일하게 Structured Output Parser 노드를 추가하고, 프롬프트에 지정한대로 5가지 응답을 추가해주도록 하자. 마찬가지로 아래의 JSON Structure에는 잘려서 안나와있지만, 제공해준 프롬프트대로 apiSummary와 inference Property까지 모두 추가해주어야 한다.

 

 

 

[ 테스트해보기 ]

마지막으로 다음의 주어진 입력값을 제공하여, 실제 원하는대로 응답이 나오는지 테스트해보도록 하자.

httpMethod: POST,
requestUrl: /pet/{petId}/uploadImage,
cause: com.mangkyu.PetRepository$PetNotFoundException: cannot find pet
	at com.mangkyu.PetRepository.findById(PetRepository.java:10)
	at com.mangkyu.PetRepository$$SpringCGLIB$$0.findById(<generated>)
	at com.mangkyu.PetService.uploadImage(PetService.java:17)
	at com.mangkyu.PetController.uploadImage(PetController.java:19)

 

 

그러면 다음과 같이 원하는 대로 응답한 결과를 제공받게 될 것이다.

 

 

 

[ API 연동하기 ]

Flowise는 API 연동이 가능하기 때문에 우상단의 API 연동 부분을 통해 다음과 같이 연동 정보를 확인할 수 있다. 따라서 해당 정보를 활용해 애플리케이션에서 API 호출과 응답으로 연동해주도록 하자.

 

 

지금까지 구성한 Flow 역시 다음의 파일에 정리되어 있으니, 필요하다면 해당 Flow를 Load하여 사용하도록 하자.

error_analyze_flow.json
0.04MB

 

 

 

 

해당 부분을 서비스에서 활용 및 고도화하려면 여러 가지 정책들이 필요하다. 관련된 부분은 토스 테크 블로그에 보다 자세히 작성해두었으니, 해당 내용을 이어서 참고해주도록 하자.

https://toss.tech/article/flowise-llm-error-analysis-automation

 

Flowise와 LLM을 활용한 에러 분석 자동화

LLM으로 에러 원인 분석과 해결 방안 제시까지 자동화하고, 팀의 생산성을 향상시킨 이야기를 들려드립니다.

toss.tech

 

 

 

 

아직 국내의 IT 업계는 LLM의 도입과 이를 통한 자동화가 높은 수준에 이르지 못했다고 합니다. 뛰어난 인재들이 많은 국내 개발자들이, 연동 및 활용 방법에 대해 빠르게 학습하고 적용할 수 있으면 모두에게 좋을 것 같습니다.

 

 

 

 

 

반응형
댓글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG more
«   2025/07   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
글 보관함