RAG + 시맨틱 마크업
다른 언어: English Español Português 中文
소프트웨어 프로젝트간에 문서화의 중요성은 차이가 있지만, 모든 중요한 문서화조차도 본질적으로 보조적인 역할을 합니다. 프로그램이 올바르게 작동하는 데 필요한 것은 아닙니다. 문서화가 프로그램과 데이터를 공유해도 연결은 여전히 단방향입니다. 사용자 대면 문서화는 제품을 반영하며 제품의 작동 방식을 변경하지 않습니다.
이러한 사실의 주요 이유는 순전히 기술적인 것입니다. 만약 자연어 내의 명령이 충분히 특정할 수 있고, 그리고 컴퓨터가 그것들을 해석하는 데 뛰어나다면, 문서작성만으로 새로운 기능과 수정 사항을 구현할 수 있습니다. 이것은 익숙하게 들리지 않나요?
프로그래밍이 완전히 자연어로 가능할지에 대한 논쟁이 계속되고 있는 동안, 이것은 실제로 소프트웨어 개발의 접근성에 대한 변화이며, 프로그램이 작동하는 방식에 새로운 것을 도입하는 것이 아닙니다. 결국, 우리는 여전히 동일한 바이너리를 얻고 있을 것이며, 이제 인정해야 할만한 컴파일러가 추가로 관여할 뿐입니다.
AI가 기능을 다른 방식으로 이끌 수 있을까요? 오늘 나는 자연어 처리를 직접 활용하는 JetBrains IDEs에서 최근의 AI 주도 기능 중 하나를 다루고자 합니다. 이 기능은 대량의 문서화를 굉장히 유용한 개발 자산으로 전환합니다.
작업 검색
버전 2024.3부터 JetBrains IDEs의 AI 어시스턴트는 IDE 작업에 접근할 수 있으며 문제에 맞는 올바른 작업을 찾는 데 도움을 줍니다. 또한 작업을 대신해서 실행해주기도 합니다:
앞서 언급했듯이, 이 기능은 문서화에 의해 구동됩니다. 좋은 오래된 코드는 일부를 차지하면서도, 올바른 작업의 선택은 전적으로 RAG (검색 강화 생성)의 고급 형태에만 의존합니다 – 여러 LLM 기능이나 특수 매핑 없이도요.
자세한 내용을 다루기 전에, RAG의 개념을 간단히 다시 살펴봅시다.
RAG
검색 강화 생성 (RAG)는 LLM 응답의 정확성과 기반을 향상시키는 데 흔히 사용하는 기술입니다. LLM이 그들의 훈련 데이터 및 자주 변경되어 미세 조정이 비현실적인 사실들을 넘어서 응답을 제공해야 하는 경우에 특히 효과적입니다.
가장 일반적인 형태에서, 이 기술은 문서화를 인덱싱하는 작업을 포함합니다. 이 인덱스에서 키는 문서 요소의 의미를 반영하며, embeddings에 의해 표현되는 반면, 값은 요소의 콘텐츠 또는 요소 자체에 대한 참조에 해당합니다. 키의 숫자 표현 덕분에, 해당 요소들은 코사인 유사도나 k-근접 이웃 (KNN)과 같은 방법을 사용하여 시맨틱적으로 검색하고 검색해 낼 수 있습니다.
RAG 기반 AI 채팅에서 무언가를 요청하면 다음과 같이 됩니다:
글꼴 크기는 어떻게 변경하나요?
시스템은 먼저 인덱스를 검색하고, 성공했다면, 결과를 프롬포트에 첨부합니다. 예를 들면:
글꼴 크기는 어떻게 변경하나요?
다음은 질문에 답할 수 있도록 도와줄 수 있는 보충 정보입니다:
-> 검색 결과가 여기에 삽입됩니다 <-
이 접근 방식을 사용하면, 제공된 보충 정보로부터 올바른 답변을 추론 할 수 있습니다. 따라서 LLM으로부터 보다 통찰력 있고 정확한 응답이 나옵니다. 최종 사용자의 관점에서 보면, 모델이 더 지적으로 보일 수 있지만, 실제로는 모델은 변하지 않았습니다. 유일한 차이점은 프롬포트에 있을 뿐입니다.
이제 이 접근 방식을 어떻게 강화할 수 있는지 살펴보겠습니다.
시맨틱 마크업
기술 문서를 작성하다면, 시맨틱 마크업의 개념에 친숙할 것입니다:
시맨틱 마크업을 통해 각 요소 뒤에 있는 “의미”를 지정합니다
예를 들어, 마크다운은 시맨틱하지 않습니다. 마크다운에서는 제목, 문단, 목록 등과 같은 일반적인 문서 요소와 또 몇 가지 타이포그래피 속성들로 작업합니다. 이 문법은 고수준 구조를 개요하고 문서를 어떻게 렌더링할지 프로세서에게 알립니다. 그러나 그것이 문서 내의 다양한 요소의 목적, 또는 의미를 표시하는 것은 아닙니다.
다음은 간단한 예입니다. 별표는 프로세서에게 문구를 기울여야 함을 나타냅니다,
HTML의 <i>
가 의미하는 것과 유사합니다:
*길 건너기 전에 양쪽을 다 봐라!*
반면에, 마크다운의 상위 집합인 MDX에는 시맨틱 속성이 있습니다. MDX는 해당 컨텐츠의 예상되는 목적을 전달할 수 있는 사용자 정의 요소를 정의하도록 허용합니다:
<Warning>
길 건너기 전에 양쪽을 다 봐라!
</Warning>
바닐라 마크다운과 달리, 이 특정 MDX 예제는 시각적 측면을 추상화하고 콘텐츠의 목적에 초점을 맞춥니다.
문서작성자로서, 우리는 <Warning>
가 기울임체를 사용해야 하든
정규 텍스트로부터 다른 방식으로 돋보이게 해야하든 신경 쓰지 않습니다.
그 스타일은 컴포넌트 자체나 CSS 스타일시트와 같은 별도의 장소에서 정의됩니다.
간략한 관심사의 분리는
코드베이스를 유지하기 쉽게 만들어주며, 컨텐츠의 의미를 기반으로 스타일을 중앙에서 변경하게 해줍니다.
완벽한 짝일까요?
JetBrains에서 우리는 문서를 Writerside를 사용하여 작성합니다. 이 도구는 마크다운과 시맨틱 XML을 문서화의 원본 형식으로 지원합니다. 아래 예제는 Writerside의 시맨틱 XML로 작성된 전형적인 문서 구조를 보여줍니다:
<chapter title="Testing" id="testing">
... some content ...
<procedure title="Navigate to tests" type="choices">
<p>
When at a symbol declaration, you can navigate to the corresponding
tests by doing one of the following:
</p>
<step>
From the main menu, select <ui-path>Navigate | Test</ui-path>.
</step>
<step>
Press <shortcut key="GotoTest"/>.
</step>
</procedure>
... more content ...
</chapter>
제공된 스니펫에는 일부 메타 정보가 포함되어 있습니다. 이것은 이미 앞에서 언급한 이유로 가치가 있지만, 추가적으로 사용하기를 막는 것은 없습니다.
<shortcut>
태그를 고려해 보십시오,
이 태그는 플랫폼 종속적인 키 바인딩을 나타냅니다.
이 태그는 중앙에서 단축키를 언급을 관리하고 검증하는 indirection layer의 일부입니다.
문서 내에서 단축키를 삽입하려면, <shortcut>
태그와
해당 작업 ID를 함께 사용하면 됩니다: 이렇게 말이죠: <shortcut key="CoolAction">
.
빌드 과정에서, 도구는 <shortcut>
요소를
사용 가능한 키맵에 대한 실제 키 바인딩으로 변환하고 검증합니다.
이 접근 방식은 문서와 제품간의 단축키를 동기화하며, 문서의 사용자들에게 선호하는 키맵을 선택하는 유연성을 제공합니다. 이 접근 방식을 보려면, IntelliJ IDEA 도움말을 방문하고 Shortcuts 메뉴에서 선택한 키맵에 따라 텍스트에서 단축키가 어떻게 변경되는지 유의해 보세요:
<shortcut>
태그의 기본 목적입니다.
이 태그가 RAG을 어떻게 향상시킬 수 있는지에 대한 이점은 무엇일까요?
가장 간단한 사용법은 AI 채팅에서 플랫폼별 단축키를 표시하는 것입니다, 도움말 페이지에서처럼 말이죠:
그러나, 더 흥미로운 부분이 있습니다. 사실들과 지시사항을 검색하기 위한 인덱스를 만드는 것과 비슷하게, 작업 ID를 찾을 수 있도록 하는 인덱스를 만들 수 있습니다.
앞에서 다룬 더 간단한 RAG 시나리오에서, 우리는 검색하고자 하는 것과 동일한 요소에서 embedding들을 생성했습니다. 그러나, 작업 ID 인덱스에 대해서는 다음과 같은 구조를 사용할 것입니다:
- 키는
<shortcut>
태그를 둘러싸는 요소로부터 파생된 embedding입니다. - 값은 해당하는
<shortcut>
태그 내의 작업 ID들입니다.
예에서, <shortcut key="GotoTest"/>
의
둘러싸는 요소는
<step>
이거나 전체 <procedure>
일 수 있습니다:
<procedure title="Navigate to tests" type="choices">
<p>
When at a symbol declaration, you can navigate to the corresponding
tests by doing one of the following:
</p>
<step>
From the main menu, select <ui-path>Navigate | Test</ui-path>.
</step>
<step>
Press <shortcut key="GotoTest"/>.
</step>
</procedure>
맥락이 중요하다
둘러싸는 요소의 내용을 인덱싱 하는 것의 중요성을 보여주기 위해, IntelliJ IDEA의 Set Value 기능을 예로 들어 보겠습니다. 이 기능은 디버그 모드에서 프로그램이 일시 중지된 동안 변수를 업데이트하게 해줍니다.
해당 작업의 ID는 SetValue
입니다.
그러나 이 ID는 자체로서는 특별히 설명적이지 않습니다.
SetValue
와 많은 다른 ID들이 프로그래밍에서 상당히 일반적인 단어 조합인 것을 고려하면,
이러한 ID들만을 기반으로 한 시맨틱 검색은
수용할 수 없는 비율의 거짓 양성과 부정을 초래할 것입니다.
추가적인 맥락을 인덱스에 포함하지 않으면,
작업은 사실상 불가능합니다.
반면에, 작업 ID와 주변 콘텐츠 간의 관계를 제시함으로써, AI 어시스턴트에게 해당 기능에 대한 자세한 내용, 일반적인 사용 사례, 제한 사항을 제공합니다. 이 정보는 검색의 정확성을 크게 향상시킵니다:
클라이언트 부분
마지막으로 AI 어시스턴트가 올바른 작업 ID를 얻게 되면, 이 작업을 제안하고 심지어는 채팅 내부에서 즉시 해당 작업을 실행하는 버튼조차도 표시할 수 있습니다:
물론, 이 부분은 단순히 UI에 버튼을 추가하는 것보다 약간 더 복잡합니다. IDE 작업이 맥락에 의존하기 때문에, 추가로 몇 가지 체크를 구현해야 합니다. 그러나 이 주제는 IntelliJ Platform 개발에 매우 특화되어 있어서, 그 자체로 별도의 토론을 요구합니다.
다른 마크업 요소들
이 게시물에서는 우선적으로 ‘작업 검색’ 기능에 주로 집중했으며,
이 기능은 Writerside의 <shortcut>
태그에서 작업 ID를 검색함으로써 작동합니다.
그러나, 이와 같은 원칙을 시맨틱 마크업 내의 많은 다른 요소 유형에 적용할 수 있습니다.
간단한 예를 들어, <ui-path> 요소를 사용하면 메뉴 항목과 같은 UI 요소들의 일련을 명시하게 되며, 이 요소들을 통해 설명된 기능에 접근해야 합니다.
<step>
Open the IDE settings (<shortcut key="ShowSettings"/>),
then navigate to <ui-path>Tools | Terminal</ui-path>.
</step>
웹 도움말에서 긴 경로를 제공하는 것은 완벽한 의미가 있습니다, 왜냐하면 웹 페이지에서 제품으로의 직접 이동은 일반적으로 실용적이지 않습니다. 그러나 반면에, 사용자가 제품 내에서 이에 대해 묻는 경우, 해당 설정 페이지를 바로 보여주는 데 있어 이유가 없습니다:
요약
몇 년 전, 많은 사람들이 Web 3.0이라는 개념을 상상했습니다. 그 아이디어는 전체 웹을 시맨틱 마크업으로 이동하여 기계가 사람처럼 사용할 수 있게 하는 것이었습니다. 이것은 이루어지지 않았지만, 현대의 도구와 기술들의 관점에서 동일한 아이디어가 다시 관련성을 가지게 된 것이 흥미롭습니다.
이 글에서 다룬 기능은 존재하는 좋은 관행들, 즉 시맨틱 마크업을 Gen AI 시스템과 함께 활용할 수 있는 한 가지 예시입니다. 탐색할 수 있는 것들이 더 많이 있습니다. 특히 RAG에 관심이 있다면, 이것은 검색 강화 생성에 대한 훌륭한 튜토리얼들의 모음입니다.
본문을 즐겁게 읽으셨나요? Gen AI로 실험하는 것을 좋아하나요? 제 블로그에는 댓글 섹션이 없지만, 귀하의 관점과 사례에 대해 듣고 싶으므로, 발밑의 연락처를 이용하여 주저하지 말고 연락해 주세요.
곧 만나요!