들어가며
앞선 글에서 RAG에 대해 DBA의 관점으로 간략하게 설명을 했습니다.
(RAG(검색 증강 생성)이란 글 참고)
ORACLE DB에서 RAG를 사용하는 방법에 대해 알아보겠습니다.
제가 테스트 한 버전은 23AI Free 버전이므로 추후 EE버전에서는 내용이 달라질 수 있습니다.
실습 시나리오
오라클에서 LOCAL LLM 인 OLLAMA를 사용하여 EXAONE MODEL에 RAG(증강검색)을 하는 테스트입니다.
대법원선고중요판결요지 라는 문서에 내용을 Chunk후 Embbeding 시켜 Vector 값을 가진 테이블을 만들었습니다. 그 테이블의 데이터를 사용해서 EXAONE LLM Model에 질의를 하는 내용으로 테스트 내용을 작성했습니다.
대법원선고중요판결요지파일은 아래의 url 링크를 통해 다운받아서 사용하세요.
파일명 : law240830(8.29.판결).pdf 다운로드 링크
실습
1. 실습 테이블 생성
위에 선고중요판결요지라는 파일을 서버에서 불러와 임베딩하여 Vector값으로 컬럼이 포함된 테이블로 생성합니다.
쿼리 가장 아래에 있는 embed_vector clob 이라는 쿼리 내용중 clob 타입을 vector로 했을 시에 테이블에 데이터가 보이지 않는 문제가 발생하여 clob 후 select 절에서 to_vector함수를 사용하여 다시 벡터화 시켰습니다.
create table dre.rag_test as
select embed_id,embed_data,to_vector(embed_vector) as embed_vector
FROM (select
dbms_vector_chain.utl_to_text(TO_BLOB(bfilename('DOC_DIR',a.file_name))) AS DOC_content_blob
from (values('대법원선고중요판결요지_240829.pdf')) a (file_name) ) dc
CROSS JOIN TABLE (
dbms_vector_chain.utl_to_embeddings(
dbms_vector_chain.utl_to_chunks(
dbms_vector_chain.utl_to_text(dc.DOC_CONTENT_BLOB)
,json('{"by":"characters","max":"250","split":"none","normalize":"all","LANGUAGE":"KOREAN"}')),
json('{"provider":"database", "model":"ONN.DISTILUSE_BASE_MULTILINGUAL_CASED_V2"}'))) t
CROSS JOIN JSON_TABLE(t.column_value, '$[*]' COLUMNS (embed_id NUMBER PATH '$.embed_id', embed_data VARCHAR2(1000) PATH '$.embed_data', embed_vector clob PATH '$.embed_vector')) AS et;
2. HOST_ACL 등록
LOCAL LLM 서버와의 통신을 위해 HOST_ACL을 등록합니다.
BEGIN
dbms_network_acl_admin.append_host_ace(
host =>'172.17.12.116',
LOWER_PORT =>'9301',
UPPER_PORT =>'9301',
ace => xs$ace_type(
privilege_list => xs$name_list('http', 'http_proxy'),
principal_name => 'DRE',
principal_type => xs_acl.ptype_db)
);
END;
/
3. ACL 등록 후 통신 Test
SELECT * FROM DBA_HOST_ACES ACES;
select utl_http.request('http://172.17.12.116:9301') from dual;
#쿼리 결과
Ollama is running
4. CREDENTIAL 생성
LLM API key 관리를 위해 CREDENTIAL 오브젝트 생성합니다.
declare
v_params json_object_t;
v_name varchar2(1000) := 'EXAONE_CRED';
v_api_token varchar2(1000) := 'ollama-key';
begin
v_params := json_object_t();
v_params.put('access_token',v_api_token);
begin
DBMS_VECTOR_CHAIN.DROP_CREDENTIAL ( CREDENTIAL_NAME => v_name);
exception
when others then
null;
end;
DBMS_VECTOR_CHAIN.CREATE_CREDENTIAL ( CREDENTIAL_NAME => v_name, PARAMS => json(v_params.to_string));
end;
/
5. LLM 테스트
ORACLE에서 LLM 서버에 질의를 해 연결상태를 점검합니다. LLM모델은 exaone3.0:8b 입니다.
declare
input clob;
params clob;
output clob;
begin
utl_http.set_body_charset('UTF-8');
input := '안녕 exaone3.0:8b 모델에 대해 설명해줘';
params := '
{
"provider": "OpenAI",
"credential_name": "EXAONE_CRED",
"url": "http://172.17.12.116:9301/v1/chat/completions",
"model": "exaone3.0:8b",
"context_length" : 2048
}';
output := dbms_vector_chain.utl_to_generate_text(input, json(params));
dbms_output.put_line(output);
if output is not null then
dbms_lob.freetemporary(output);
end if;
exception
when OTHERS THEN
DBMS_OUTPUT.PUT_LINE (SQLERRM);
DBMS_OUTPUT.PUT_LINE (SQLCODE);
end;
/
#질의 결과
-------------------------[Start Time: 2024/09/19 15:24:39]-------------------------
SQL> 안녕하세요! LG AI 연구원에서 개발한 EXO(EXpert Operating System) 3.0 기반의 8B 모델, EXAONE 3.0에 대해 설명해드릴게요.
### 주요 특징 및 장점:
1. **고성능 언어 이해 능력**:
- 한국어와 영어를 포함해 다양한 자연어 처리 작업에서 우수한 성능을 자랑합니다.
2. **초거대 AI 모델 기반**:
- 8x Nvidia A100 GPU로 학습되었으며, 약 6TFLOPS의 연산 능력을 가집니다. 이는 기존 초거대 인공지능 대비 효율적이고 강력한 계산력입니다.
3. **전문 지식 통합**:
- 방대한 양의 전문 문서 데이터를 바탕으로 다양한 산업의 최신 정보와 전문 지식을 습득할 수 있습니다.
4. **생성적 AI 능력**:
- 창작 활동 (예: 소설 작성, 음악 작곡 등)에도 뛰어난 성능을 보입니다. 이는 모델이 단순히 데이터를 분석하는데 그치지 않고 새로운 지식과 콘텐츠를 생성해 낼 수 있음을 의미합니다.
5. **한국어 특화 학습 모델**:
- 한국어에 최적화된 언어 모델로 감정 분석, 번역 작업 등에서도 우수한 성과를 보이며, 멀티모달 데이터 처리 기능이 강화되어 이미지 인식까지 확장할 수 있습니다.
6. **데이터 학습 윤리 및 프라이버시 준수**:
- 개인정보 보호 규정과 윤리적인 AI 개발 가이드라인을 철저히 준수하여 안전하게 활용 가능합니다.
### 결론적으로,
EXAONE 3.0은 여러 산업의 전문 작업 지원, 창의성 발휘 등 다양한 방면에서 효과적으로 사용될 수 있는 차세대 인공지능 모델입니다. 여러분께서 필요로 하시는 특정 분야나 적용 사례가 있다면 더 구체적인 설명도 가능하니 말씀해 주세요!
6. RAG사용을 위한 함수 생성
LLM모델은 위의 테스트에서 사용한 exaone3.0:8b 이고, Oracle DB안에 로드한 Embbeding Model인 distiluse_base_multilingual_cased_v2을 사용하여 임베딩했습니다.
펑션의 내용을 보면 p_user_question 이라는 변수를 사용자에게 입력 받아옵니다.
입력받은 데이터를 v_model_params에 JSON 타입으로 작성된 모델환경으로 질의를 날립니다.
사용자 질의 내용은 오라클 안의 임베딩 모델을 통해 사용자 질의 쿼리 벡터를 생성하고, 그 쿼리 벡터를 사용하여 DRE.RAG_TEST라는 테이블에 VECTOR_DISTANCE 함수로 벡터거리를 계산합니다.
v_k_stop_count 파라미터의 값만큼 찾고 조회를 STOP합니다. 나온 결과들을 v_sys_instruction에 정의된 내용과 v_message,v_user_question 등을 합하여 v_prompt로 만들어 dbms_vector_chain.utl_to_generate_text를 통해 LLM에 질의를 합니다.
CREATE OR REPLACE FUNCTION DRE.fn_rag_test(p_user_question VARCHAR2) RETURN CLOB
AUTHID DEFINER
IS
v_model_params JSON ;
v_user_question_vec vector;
v_prompt varchar2(1000);
v_sys_instruction varchar2(1000);
v_message clob;
v_user_question varchar2(1000);
v_k_stop_count number := 1;
output clob;
BEGIN
v_model_params := JSON('
{
"provider":"OpenAI",
"credential_name":"EXAONE_CRED",
"url": "http://172.17.12.116:9301/v1/chat/completions",
"model": "exaone3.0:8b",
"context_length" : 2048
}') ;
-- JSON형식에서 질의내용만 추출 :
v_sys_instruction := 'Please answer with only facts based on the searched content.답변은 한국어로 번역해서 대답해줘';
v_user_question := p_user_question ;
-- 질의내용에 대한 쿼리 벡터 생성
SELECT TO_VECTOR(vector_embedding(onn.distiluse_base_multilingual_cased_v2 USING v_user_question as data)) as embedding into v_user_question_vec ;
-- 텍스트 유사도 검색 (Multi-Vector Similarity Search)
select json_arrayagg(
json_object('EMBED_ID' is EMBED_ID, 'EMBED_DATA' is EMBED_DATA)
returning CLOB) into v_message
from (
SELECT EMBED_ID ,
EMBED_DATA
FROM DRE.rag_test
ORDER BY VECTOR_DISTANCE(EMBED_VECTOR , v_user_question_vec, COSINE)
FETCH FIRST v_k_stop_count ROWS ONLY WITH TARGET ACCURACY 90
);
-- 프롬프트생성
v_prompt := '
<s>[INST] {system_instruction}.
Search Data:
{insert_search_data_here}
User Query:
{user_query}
Provide a detailed response based on the search data above. [/INST]
';
v_prompt := replace(replace(replace(v_prompt,'system_instruction',v_sys_instruction),'{insert_search_data_here}', v_message),'{user_query}',v_user_question);
-- Return the substring of the CLOB within the size limit
-- output := DBMS_LOB.SUBSTR(v_prompt, 4000, 1);
utl_http.set_body_charset('UTF-8');
output := dbms_vector_chain.utl_to_generate_text(v_prompt, v_model_params);
RETURN output;
END;
/
7. RAG 실행
위에서 만들 RAG 함수를 사용하여 Ollama 서버에 증강검색을 합니다.
DECLARE
p_user_question CLOB := '마약류관리에관한법률위반(향정) 를 파기환송한 이유에 대해 알려줘'; -- 여기에 p_user_question의 값을 직접 입력
output CLOB;
BEGIN
output := DRE.fn_rag_test(p_user_question );
DBMS_OUTPUT.PUT_LINE('Output: ' || output);
END;
/
-------------------------[Start Time: 2024/09/12 07:46:11]-------------------------
SQL> Output: 마약류관리에 관한 법률 위반(향정) 사건을 파기환송한 이유는 피고인 및 그와 공범관계에 있던 A의 사례로 볼 수 있습니다. 주된 쟁점은 검사 또는 사법경찰관 작성 피의자신문조서의 증거능력이었습니다.
아래는 이를 근거로 한 상세 설명입니다:
1. **검사 또는 사법경찰관 작성 피의자신문조서**: 피고인과 공범인 A에 대한 경우, 이들 작성한 신문조서가 법적으로 증거 능력을 가지는지 여부가 중요한 쟁점으로 다뤄졌습니다.
2. ***형사소송법 제312조***: 형사소송법 제312조는 검사 또는 경찰 작성의 피의자신문조서에 대한 규정을 담고 있으며, 이를 통하여 피고인이 진술거부권과 변호인 조력을 받을 권리를 보호하면서도 실질적인 진술 내용이 신뢰할 만한지 평가합니다.
- 동 조항에 따르면 피의자나 피고인이 경찰이나 검찰 조사 과정에서 자백하거나 진술한 내용이 진정한 것인지를 판단하기 위해 몇 가지 요건들(예: 피고인의 자발성, 임의성)을 충족해야 합니다.
3. **원심 판결**: 원심(아래 단계 법원)은 이러한 형사 소송법 규정과 그 해석에 따라 본 사건에서 검사 또는 사법경찰관 작성 피의자신문조서를 적법하게 인정하고 유죄판결을 내렸습니다. 그러나 위에서 언급된 요건들이 충분히 충족되지 않았다고 판단하여 사후 증거능력이 문제가 되었고 이에 대한 상고가 제기됐습니다.
4. **대법원 판결**: 대법원은 원심의 판단이 부족함을 지적하며 사건을 상급심으로 돌려보냈습니다(즉, 파기환송). 대법원은 보다 면밀한 검토를 통해 실제 조사 과정에서 진술 강요 여부와 자발성 등에 대해 엄격히 재검토할 필요성이 있다고 보았던 것입니다.
- 또한, 구체적인 사실관계 분석 및 관련 법령 적용에 있어서 추가 조사가 요구된 상황이었기 때문으로 추정됩니다.
따라서, 마약류관리에 관한 법률위반(향정)을 기소한 본 사건에서는 법원들 간 해석 차이와 이에 따른 심리 부족 등의 문제로 인해 최종 판단은 상급심인 대법원의 재검토 아래 다시 진행되게 된 것입니다.
마치며
테스트를 하면서 신기하다는 느낌은 받았지만, RAG를 활용하여 제품을 만들어서 활용하는 모습은 시간이 조금 걸릴것 같다라는 생각을 했습니다. 하지만, AI기술의 발전 속도를 보면 머지않아 우리 실생활에 빠질 수 없는 중요한 요소가 될 것이라고 생각이 듭니다.
ORACLE DB에서 AI를 활용하여 무엇을 할 수 있다는게 신기했습니다. 제가 테스트한 ORACLE 23AI FREE버전은 23.5인데 dbms_vector_chain.utl_to_generate_text 라는 함수를 사용하여 LLM쪽으로 질의를 하였습니다. 문제는 dbms_vector_chain.utl_to_generate_text 이 함수가 처음에는 VARCHAR2(4000)의 제한이 있었는데 현재 벡터서치 가이드에서는 CLOB로 변경된 것으로 보입니다.
가이드에서처럼 Ollama Provider제공과 위 함수의 clob 지원이 되는 새로운 버전이 빨리 나왔으면 하는 바램입니다.
'ORACLE 23ai' 카테고리의 다른 글
Oracle Vector Index1-HNSW (2) | 2024.09.19 |
---|---|
Oracle Embedding Model Load (1) | 2024.09.05 |
Embedding (1) | 2024.08.28 |
RAG(검색 증강 생성)이란 (0) | 2024.08.26 |