๋žญ์ฒด์ธ(๐Ÿฆœ๏ธ๐Ÿ”—LangChain)๊ณผ ํ•จ๊ป˜ ๋ฐ์ดํ„ฐ์…‹ ์ž๋™ ๋ผ๋ฒจ๋Ÿฌ ๋งŒ๋“ค๊ธฐ

Jiwon Kangยท2023๋…„ 6์›” 26์ผ
1
post-thumbnail

๋ชฉํ‘œ: ์ž๋™ ๋ผ๋ฒจ๋Ÿฌ ๋งŒ๋“ค๊ธฐ

  • ๋ชฉํ‘œ๋Š” LLM์„ ํ™œ์šฉํ•ด ์ž๋™ ๋ผ๋ฒจ๋ง ํ…Œ์Šคํฌ๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ธฐ
    • ํ…์ŠคํŠธ๊ฐ€ ์ฃผ์–ด์ง€๋ฉด ํ”„๋กฌํ”„ํŠธ ๋‚ด์˜ ๊ฐ€์ด๋“œ๋ผ์ธ์„ ๋ณด๊ณ  ๋ผ๋ฒจ๋งํ•˜๋Š” ๊ฒƒ์ด ๋ชฉํ‘œ!
    • ์ด๋ ‡๊ฒŒ ๋ผ๋ฒจ๋งํ•ด์„œ ๋‹ค์šด์ŠคํŠธ๋ฆผ ํ…Œ์Šคํฌ์— ์‚ฌ์šฉํ•ด๋„ ์ข‹๊ฒ ์ง€๋งŒ, ์šฐ์„ ์€ ๋˜ ํ•˜๋‚˜์˜ ๋ผ๋ฒจ๋Ÿฌ ์—ญํ• ์„ ์ˆ˜ํ–‰ํ•˜๋„๋ก ํ•˜๋Š”๊ฒŒ ๋ชฉ์ 
  • ํ•„์š”ํ•œ ์žฌ๋ฃŒ
    • ๋ผ๋ฒจ๋งํ•  Raw ํ…์ŠคํŠธ
    • ๋ผ๋ฒจ๋ง ๊ฐ€์ด๋“œ๋ผ์ธ (์„ ํƒ, ํ”„๋กฌํ”„ํŠธ ์„ธ๋ถ€ ์ž‘์„ฑ์‹œ ์‚ฌ์šฉ)
    • ๋ผ๋ฒจ๋งํ•  ์นดํ…Œ๊ณ ๋ฆฌ ์ข…๋ฅ˜
    • N๋ช…์˜ ๋ผ๋ฒจ๋Ÿฌ๊ฐ€ ๋ผ๋ฒจ๋งํ•œ ๋ฐ์ดํ„ฐ (์„ ํƒ, ํ‰๊ฐ€์‹œ ์‚ฌ์šฉ)
  • ์‚ฌ์šฉ ๋ฐ์ดํ„ฐ
  • ๐Ÿ‘พ Jupyter Notebook (Code)
    • ํฌ์ŠคํŠธ์—์„œ ์‚ฌ์šฉํ•œ ๋…ธํŠธ๋ถ ํŒŒ์ผ

๐Ÿฆœ๏ธ๐Ÿ”—LangChain

  • ์ด๋ฒˆ์—๋Š” OpenAI API๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ๋žญ์ฒด์ธ์ด๋ผ๋Š” ํŒจํ‚ค์ง€๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค
  • ๋žญ์ฒด์ธ์ด๋ผ๋Š” ํŒจํ‚ค์ง€๋Š” OpenAI API๋ฅผ ๋น„๋กฏํ•œ LLM์„ ํ™œ์šฉํ•˜๊ธฐ ํŽธํ•˜๊ฒŒ ๋งŒ๋“œ๋Š” ํ”„๋ ˆ์ž„์›Œํฌ๋‹ค. huggingface๋ž‘ ๋น„์Šทํ•œ ์—ญํ• ์„ ํ•œ๋‹ค๊ณ  ๋ณด๋ฉด ์‰ฝ๋‹ค
  • ๋žญ์ฒด์ธ์—๋Š” ์—ฌ๋Ÿฌ๊ฐ€์ง€ ๊ธฐ๋Šฅ๋“ค์ด ์žˆ๋Š”๋ฐ ์šฐ๋ฆฌ๊ฐ€ ์ด๋ฒˆ์— ์“ธ๊ฑด ์•„๋ž˜์™€ ๊ฐ™๋‹ค
    • ํ”„๋กฌํ”„ํŠธ ํ…œํ”Œ๋ฆฟ ๊ธฐ๋Šฅ: ๊ฐ„ํŽธํ•˜๊ฒŒ ์ž…๋ ฅ ํ”„๋กฌํ”„ํŠธ์™€ ์ถœ๋ ฅ๊ฐ’์„ ์ •์ œํ•  ์ˆ˜ ์žˆ๋‹ค
    • ํ…์ŠคํŠธ ์ž„๋ฒ ๋”ฉ + ์˜ˆ์ œ ์„ ํƒ + ๋ฒกํ„ฐ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๋™ ๊ธฐ๋Šฅ: ํ”„๋กฌํ”„ํŠธ ์ž‘์„ฑ์‹œ ์˜ˆ์ œ๋ฅผ ํ•จ๊ป˜ ์ฃผ์ž…ํ•˜๋ฉด ์ข‹์€ ๊ฒฐ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๋Š”๋ฐ, ์˜ˆ์ œ๋ฅผ ์„ ํƒํ•  ๋•Œ ๋ผ๋ฒจ๋ง ๋Œ€์ƒ ํ…์ŠคํŠธ์™€ ๋น„์Šทํ•œ ์˜ˆ์ œ๋ฅผ ์„ ํƒํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค€๋‹ค

1. ํ”„๋กฌํ”„ํŠธ ์ž‘์„ฑํ•˜๊ธฐ

  • ๋จผ์ € ์ง€์‹œ๋ฌธ๊ณผ ์–ด๋–ป๊ฒŒ ์ง€์‹œ๋ฌธ์˜ ํ…Œ์Šคํฌ๋ฅผ ํ•ด๊ฒฐํ• ์ง€์— ๋Œ€ํ•œ ๊ฐ€์ด๋“œ๋ผ์ธ์„ ์ ์–ด์ฃผ์ž
label_template = """์•„๋ž˜์˜ ๋ผ๋ฒจ๋ง ๊ฐ€์ด๋“œ๋ผ์ธ์— ๋”ฐ๋ผ ๋‹จ๊ณ„์ ์œผ๋กœ ์ฃผ์–ด์ง„ ํ…์ŠคํŠธ์— ๋Œ€ํ•œ ํ˜์˜คํ‘œํ˜„์„ ๋ถ„๋ฅ˜ํ•˜์„ธ์š”.

1. ํ˜์˜ค ํ‘œํ˜„์˜ ์ •์˜: ํŠน์ • ์‚ฌํšŒ์  (์†Œ์ˆ˜์ž) ์ง‘๋‹จ์— ๋Œ€ํ•œ ์ ๋Œ€์  ๋ฐœ์–ธ, ์กฐ๋กฑ, ํฌํ™”ํ™”, ํŽธ๊ฒฌ์„ ์žฌ์ƒ์‚ฐํ•˜๋Š” ํ‘œํ˜„์œผ๋กœ, 
๋Œ€์ƒ์— ๋Œ€ํ•œ ๊ณ ์ •๊ด€๋…,๋Œ€์ƒ์˜ ํŠน์„ฑ์ด๋‚˜ ์„ฑํ–ฅ์„ ํŠน์ •ํ•œ ํ†ต๋…์— ๊ณ ์ฐฉ์‹œํ‚ค๋Š” ๋ฐœ์–ธ์„ ํฌํ•จ. ๋‹จ, ํ™”์ž ์Šค์Šค๋กœ๋ฅผ ์ž์กฐ์ ์œผ๋กœ ํ‘œํ˜„ํ•˜๋Š” ๊ฒฝ์šฐ๋Š” ํ˜์˜ค ๋ฐœ์–ธ์ด ์•„๋‹˜
   
2. ๋ผ๋ฒจ๋ง ๋‹จ๊ณ„:
   - Step 1: ์ฃผ์–ด์ง„ text๋ฅผ ํ˜์˜คํ‘œํ˜„, ์•…ํ”Œ/์š•์„ค, clean ์ค‘ ํ•˜๋‚˜๋กœ ๋ถ„๋ฅ˜
       - Clean: ํ˜์˜คํ‘œํ˜„, ์š•์„ค, ๋ถˆ์พŒ๊ฐ, ์Œ๋ž€์„ฑ ๋‚ด์šฉ์„ ํฌํ•จํ•˜๊ณ  ์žˆ์ง€ ์•Š์€ ์ผ๋ฐ˜ ๋ฌธ์žฅ
       - ์•…ํ”Œ/์š•์„ค: ์–ด๋–ค ์ง‘๋‹จ์„ ํ–ฅํ•œ ํ˜์˜ค ํ‘œํ˜„์ธ์ง€ ์ง€์นญํ•  ์ˆ˜๋Š” ์—†์ง€๋งŒ, ํƒ€์ธ ํ˜น์€ ์™ธ๋ชจ์— ๋Œ€ํ•œ ๋น„ํ•˜/์š•์„ค์ด ํฌํ•จ๋˜์–ด ์žˆ๊ฑฐ๋‚˜, ๋ถˆ์พŒ๊ฐ์„ ์ฃผ๊ฑฐ๋‚˜, ์•…ํ”Œ๊ณผ ์Œ๋ž€์„ฑ ๋ฌธ์žฅ
       - ํ˜์˜คํ‘œํ˜„: Step2๋กœ ์ด๋™
   - Step 2: ํ˜์˜คํ‘œํ˜„์ผ ๊ฒฝ์šฐ ํ˜์˜ค ์นดํ…Œ๊ณ ๋ฆฌ ์ค‘์—์„œ ํ•ด๋‹น๋˜๋Š” ์นดํ…Œ๊ณ ๋ฆฌ๋ฅผ multi-label๋กœ ๋ถ„๋ฅ˜
       - ์—ฌ์„ฑ/๊ฐ€์กฑ: ์—ฌ์„ฑ์„ฑ ๋ฐ ์—ฌ์„ฑ์˜ ์„ฑ์—ญํ• ์— ๋Œ€ํ•œ ํ†ต๋…์„ ๊ณ ์ฐฉ์‹œํ‚ค๋Š” ๋ฐœ์–ธ, ์—ฌ์„ฑ ์ฐจ๋ณ„์„ ํฌํ™”ํ™”ํ•˜๋Š” ๋ฐœ์–ธ, ํŽ˜๋ฏธ๋‹ˆ์ฆ˜ยท์—ฌ์„ฑ๊ฐ€์กฑ๋ถ€ ์ „๋ฐ˜์— ๋Œ€ํ•œ ์•…ํ”Œ, ๊ฐ„ํ˜ธ์‚ฌ, ์—ฌ๊ฒฝ ๋“ฑ ์—ฌ์„ฑ์„ ์ค‘์‹ฌ์œผ๋กœ ๊ตฌ์„ฑ๋œ ์ง‘๋‹จ, ๋น„ํ˜ผ์ฃผ์˜์ž, ๋ฏธํ˜ผ๋ชจ, ๋™์„ฑ ๋ถ€๋ถ€ ๋“ฑ ์ „ํ†ต์ ์ด์ง€ ์•Š์€ ํ˜•์‹์˜ ๊ฐ€์กฑ์— ๋Œ€ํ•œ ํ˜์˜ค ๋ฐœ์–ธ
       - ๋‚จ์„ฑ: ์ง‘๋‹จ์œผ๋กœ์„œ์˜ ๋‚จ์„ฑ ์ผ๋ฐ˜์„ ๋น„ํ•˜, ์กฐ๋กฑ, ํฌํ™”ํ™”ํ•˜๋Š” ๋ฐœ์–ธ
       - ์„ฑ์†Œ์ˆ˜์ž: ์„ฑ์†Œ์ˆ˜์ž(๋ ˆ์ฆˆ๋น„์–ธ, ๊ฒŒ์ด, ๋ฐ”์ด์„น์Šˆ์–ผ, ํŠธ๋žœ์Šค์  ๋” ๋“ฑ)๋ฅผ ๋ฐฐ์ฒ™ํ•˜๋Š” ๋ฐœ์–ธ์ด๋‚˜ ์ด์„ฑ์•  ์ด์™ธ์˜ ์„น์Šˆ์–ผ๋ฆฌํ‹ฐ๋ฅผ ๋ถ€์ •์ ์œผ๋กœ ๋ฌ˜์‚ฌํ•˜๊ฑฐ๋‚˜ ์„ฑ์†Œ์ˆ˜์ž๋ฅผ ํฌํ™”ํ™”ํ•˜๋Š” ํ‘œํ˜„
       - ์ธ์ข…/๊ตญ์ : ํŠน์ • ์ธ์ข…๊ณผ ๊ตญ์ ์— ๋Œ€ํ•œ ์š•์„ค, ๊ณ ์ •๊ด€๋…, ์กฐ๋กฑ. ์ข…๊ตยท์ธ์ข…ยท๊ตญ๊ฐ€์— ๋Œ€ํ•ด ์•”๋ฌต์ ์œผ๋กœ ํ•จ๊ป˜ ์ง€์นญํ•˜๋Š” ์†Œ์žฌ์˜ ๋ฐœ์–ธ
       - ์—ฐ๋ น:ํŠน์ • ์„ธ๋Œ€๋‚˜ ์—ฐ๋ น์„ ๋น„ํ•˜ํ•˜๋Š” ์€์–ด์˜ ์‚ฌ์šฉ ๋ฐ ํ˜์˜ค ํ‘œํ˜„
       - ์ง€์—ญ: ํŠน์ • ์ง€์—ญ์— ๋Œ€ํ•œ ์€์–ด ๋ฐ ํ˜์˜ค ํ‘œํ˜„์„ ๋ถ„๋ฅ˜
       - ์ข…๊ต: ํŠน์ • ์ข…๊ต์— ๋Œ€ํ•œ ํ˜์˜ค ๋ฐ ์ข…๊ต์ธ ์ง‘๋‹จ์— ๋Œ€ํ•œ ๋น„๋‚œ
       - ๊ธฐํƒ€ํ˜์˜ค: ์œ„์—์„œ ์ •์˜ํ•œ ์นดํ…Œ๊ณ ๋ฆฌ ์ด์™ธ์˜ ์ง‘๋‹จ์„ ๋Œ€์ƒ์œผ๋กœ ํ•˜๋Š” ํ˜์˜ค ํ‘œํ˜„
"""
  • ๋ฐ์ดํ„ฐ์…‹ README.md์— ๊ฐ€์ด๋“œ๋ผ์ธ์ด ์ œ๋ฒ• ์ž˜ ๋‚˜์™€์žˆ๋Š” ํŽธ์ด๋ผ ๊ฑฐ์˜ ๊ทธ๋Œ€๋กœ ๊ฐ€์ ธ์™”๋‹ค

2. ํ”„๋กฌํ”„ํŠธ ํฌ๋งทํŒ…

  • ์•ž์„œ ์ž‘์„ฑํ•œ ํ”„๋กฌํ”„ํŠธ๋ฅผ ๊ทธ๋Œ€๋กœ ๋„ฃ์ง€ ์•Š๊ณ  ์˜ˆ์ œ์™€ ์ž…๋ ฅ๊ฐ’, ์ž…๋ ฅ๊ฐ’ ํ˜•ํƒœ๋ฅผ ์š”์ฒญํ•˜๋Š” ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ถ”๊ฐ€ํ•ด์„œ ๋„ฃ์„๊ฑฐ๋‹ค
fewshot_template = """
{label_template}

For example:
text: "๊ผญ ํ‚ค ์ž‘์€ ๊ธ‰์‹์ถฉ์ด ์ด๋Ÿฐ ๊ธ€ ์”€"
label: "์—ฐ๋ น"

Input:
text: "{text}"

{format_instructions}
"""
  • label_template: ์ง€์‹œ๋ฌธ + ๋ผ๋ฒจ๋ง ๊ฐ€์ด๋“œ๋ผ์ธ ์กฐํ•ฉ์˜ ๊ธ€
  • text: ๋ผ๋ฒจ๋งํ•  ํƒ€๊ฒŸ ํ…์ŠคํŠธ
  • format_instructions: ๋ชจ๋ธ์˜ ์•„์›ƒํ’‹์ด ๋“ค์–ด๊ฐˆ ๊ณณ์œผ๋กœ, ๋žญ์ฒด์ธ์˜ StructuredOutputParser ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๋ฉด ๊ฒฐ๊ณผ์— ๋Œ€ํ•œ ํ›„์ฒ˜๋ฆฌ๊ฐ€ ์‰ฝ๋„๋ก JSON ํ˜•ํƒœ๋กœ ๋งŒ๋“ค์–ด์ฃผ๋Š” ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ž๋™์œผ๋กœ ์ฃผ์ž…ํ•ด์ค€๋‹ค. ์•„๋ž˜์ฒ˜๋Ÿผ ์‚ฌ์šฉํ•˜๋ฉด๋œ๋‹ค
label_schema = ResponseSchema(
    name="label",
    description=""
)

response_schemas = [label_schema]
output_parser = StructuredOutputParser.from_response_schemas(response_schemas)
format_instructions = output_parser.get_format_instructions()
โ—๏ธํฌ๋งทํŒ… ํ›„ ์ตœ์ข… ํ”„๋กฌํ”„ํŠธ ์˜ˆ์‹œ

์•„๋ž˜์˜ ๋ผ๋ฒจ๋ง ๊ฐ€์ด๋“œ๋ผ์ธ์— ๋”ฐ๋ผ ๋‹จ๊ณ„์ ์œผ๋กœ ์ฃผ์–ด์ง„ ํ…์ŠคํŠธ์— ๋Œ€ํ•œ ํ˜์˜คํ‘œํ˜„์„ ๋ถ„๋ฅ˜ํ•˜์„ธ์š”.

  1. ํ˜์˜ค ํ‘œํ˜„์˜ ์ •์˜: ํŠน์ • ์‚ฌํšŒ์  (์†Œ์ˆ˜์ž) ์ง‘๋‹จ์— ๋Œ€ํ•œ ์ ๋Œ€์  ๋ฐœ์–ธ, ์กฐ๋กฑ, ํฌํ™”ํ™”, ํŽธ๊ฒฌ์„ ์žฌ์ƒ์‚ฐํ•˜๋Š” ํ‘œํ˜„์œผ๋กœ,
    ๋Œ€์ƒ์— ๋Œ€ํ•œ ๊ณ ์ •๊ด€๋…,๋Œ€์ƒ์˜ ํŠน์„ฑ์ด๋‚˜ ์„ฑํ–ฅ์„ ํŠน์ •ํ•œ ํ†ต๋…์— ๊ณ ์ฐฉ์‹œํ‚ค๋Š” ๋ฐœ์–ธ์„ ํฌํ•จ. ๋‹จ, ํ™”์ž ์Šค์Šค๋กœ๋ฅผ ์ž์กฐ์ ์œผ๋กœ ํ‘œํ˜„ํ•˜๋Š” ๊ฒฝ์šฐ๋Š” ํ˜์˜ค ๋ฐœ์–ธ์ด ์•„๋‹˜
  2. ๋ผ๋ฒจ๋ง ๋‹จ๊ณ„:
    • Step 1: ์ฃผ์–ด์ง„ text๋ฅผ ํ˜์˜คํ‘œํ˜„, ์•…ํ”Œ/์š•์„ค, clean ์ค‘ ํ•˜๋‚˜๋กœ ๋ถ„๋ฅ˜
      • Clean: ํ˜์˜คํ‘œํ˜„, ์š•์„ค, ๋ถˆ์พŒ๊ฐ, ์Œ๋ž€์„ฑ ๋‚ด์šฉ์„ ํฌํ•จํ•˜๊ณ  ์žˆ์ง€ ์•Š์€ ์ผ๋ฐ˜ ๋ฌธ์žฅ
      • ์•…ํ”Œ/์š•์„ค: ์–ด๋–ค ์ง‘๋‹จ์„ ํ–ฅํ•œ ํ˜์˜ค ํ‘œํ˜„์ธ์ง€ ์ง€์นญํ•  ์ˆ˜๋Š” ์—†์ง€๋งŒ, ํƒ€์ธ ํ˜น์€ ์™ธ๋ชจ์— ๋Œ€ํ•œ ๋น„ํ•˜/์š•์„ค์ด ํฌํ•จ๋˜์–ด ์žˆ๊ฑฐ๋‚˜, ๋ถˆ์พŒ๊ฐ์„ ์ฃผ๊ฑฐ๋‚˜, ์•…ํ”Œ๊ณผ ์Œ๋ž€์„ฑ ๋ฌธ์žฅ
      • ํ˜์˜คํ‘œํ˜„: Step2๋กœ ์ด๋™
    • Step 2: ํ˜์˜คํ‘œํ˜„์ผ ๊ฒฝ์šฐ ํ˜์˜ค ์นดํ…Œ๊ณ ๋ฆฌ ์ค‘์—์„œ ํ•ด๋‹น๋˜๋Š” ์นดํ…Œ๊ณ ๋ฆฌ๋ฅผ multi-label๋กœ ๋ถ„๋ฅ˜
      • ์—ฌ์„ฑ/๊ฐ€์กฑ: ์—ฌ์„ฑ์„ฑ ๋ฐ ์—ฌ์„ฑ์˜ ์„ฑ์—ญํ• ์— ๋Œ€ํ•œ ํ†ต๋…์„ ๊ณ ์ฐฉ์‹œํ‚ค๋Š” ๋ฐœ์–ธ, ์—ฌ์„ฑ ์ฐจ๋ณ„์„ ํฌํ™”ํ™”ํ•˜๋Š” ๋ฐœ์–ธ, ํŽ˜๋ฏธ๋‹ˆ์ฆ˜ยท์—ฌ์„ฑ๊ฐ€์กฑ๋ถ€ ์ „๋ฐ˜์— ๋Œ€ํ•œ ์•…ํ”Œ, ๊ฐ„ํ˜ธ์‚ฌ, ์—ฌ๊ฒฝ ๋“ฑ ์—ฌ์„ฑ์„ ์ค‘์‹ฌ์œผ๋กœ ๊ตฌ์„ฑ๋œ ์ง‘๋‹จ, ๋น„ํ˜ผ์ฃผ์˜์ž, ๋ฏธํ˜ผ๋ชจ, ๋™์„ฑ ๋ถ€๋ถ€ ๋“ฑ ์ „ํ†ต์ ์ด์ง€ ์•Š์€ ํ˜•์‹์˜ ๊ฐ€์กฑ์— ๋Œ€ํ•œ ํ˜์˜ค ๋ฐœ์–ธ
      • ๋‚จ์„ฑ: ์ง‘๋‹จ์œผ๋กœ์„œ์˜ ๋‚จ์„ฑ ์ผ๋ฐ˜์„ ๋น„ํ•˜, ์กฐ๋กฑ, ํฌํ™”ํ™”ํ•˜๋Š” ๋ฐœ์–ธ
      • ์„ฑ์†Œ์ˆ˜์ž: ์„ฑ์†Œ์ˆ˜์ž(๋ ˆ์ฆˆ๋น„์–ธ, ๊ฒŒ์ด, ๋ฐ”์ด์„น์Šˆ์–ผ, ํŠธ๋žœ์Šค์  ๋” ๋“ฑ)๋ฅผ ๋ฐฐ์ฒ™ํ•˜๋Š” ๋ฐœ์–ธ์ด๋‚˜ ์ด์„ฑ์•  ์ด์™ธ์˜ ์„น์Šˆ์–ผ๋ฆฌํ‹ฐ๋ฅผ ๋ถ€์ •์ ์œผ๋กœ ๋ฌ˜์‚ฌํ•˜๊ฑฐ๋‚˜ ์„ฑ์†Œ์ˆ˜์ž๋ฅผ ํฌํ™”ํ™”ํ•˜๋Š” ํ‘œํ˜„
      • ์ธ์ข…/๊ตญ์ : ํŠน์ • ์ธ์ข…๊ณผ ๊ตญ์ ์— ๋Œ€ํ•œ ์š•์„ค, ๊ณ ์ •๊ด€๋…, ์กฐ๋กฑ. ์ข…๊ตยท์ธ์ข…ยท๊ตญ๊ฐ€์— ๋Œ€ํ•ด ์•”๋ฌต์ ์œผ๋กœ ํ•จ๊ป˜ ์ง€์นญํ•˜๋Š” ์†Œ์žฌ์˜ ๋ฐœ์–ธ
      • ์—ฐ๋ น:ํŠน์ • ์„ธ๋Œ€๋‚˜ ์—ฐ๋ น์„ ๋น„ํ•˜ํ•˜๋Š” ์€์–ด์˜ ์‚ฌ์šฉ ๋ฐ ํ˜์˜ค ํ‘œํ˜„
      • ์ง€์—ญ: ํŠน์ • ์ง€์—ญ์— ๋Œ€ํ•œ ์€์–ด ๋ฐ ํ˜์˜ค ํ‘œํ˜„์„ ๋ถ„๋ฅ˜
      • ์ข…๊ต: ํŠน์ • ์ข…๊ต์— ๋Œ€ํ•œ ํ˜์˜ค ๋ฐ ์ข…๊ต์ธ ์ง‘๋‹จ์— ๋Œ€ํ•œ ๋น„๋‚œ
      • ๊ธฐํƒ€ํ˜์˜ค: ์œ„์—์„œ ์ •์˜ํ•œ ์นดํ…Œ๊ณ ๋ฆฌ ์ด์™ธ์˜ ์ง‘๋‹จ์„ ๋Œ€์ƒ์œผ๋กœ ํ•˜๋Š” ํ˜์˜ค ํ‘œํ˜„

For example:
text: "๊ผญ ํ‚ค ์ž‘์€ ๊ธ‰์‹์ถฉ์ด ์ด๋Ÿฐ ๊ธ€ ์”€"
label: "์—ฐ๋ น"

Input:
text: "๋‚จ์ž๋ผ๋ฆฌ ์˜จ๊ฐ–์–ด๋ฌธ์ง“ํ•˜๋Š” ๋ ˆ์ฆˆ๋น„์–ธ๋‹˜๋“ค ์ง„์งœ ๊ดด๋กญ์ง€.."

The output should be a markdown code snippet formatted in the following schema, including the leading and trailing "json" and "":

{
	"label": string  // 
}

3. ๋ชจ๋ธ ์‹คํ–‰

  • ์ด์ œ ํ”„๋กฌํ”„ํŠธ๋ฅผ ๋ชจ๋ธ์— ๋„ฃ์–ด์ฃผ์ž
chat = ChatOpenAI(temperature=0.0)

def autolabel_with_fewshot(input_text):
    messages = prompt_template.format_messages(
        label_template=label_template,
        text = input_text, # input text
        format_instructions = format_instructions
        )
    
    
    response = chat(messages)
    return output_parser.parse(response.content)
    
exp1_result = []

for input_text in tqdm(test_df['๋ฌธ์žฅ'].values):
    exp1_result.append(autolabel_with_fewshot(input_text))
  • ์š”๊ธˆ์ด ๋ถ€๊ณผ๋ผ์„œ ๋‘๋ ค์› ์ง€๋งŒ (์Šฌํ”ˆ ์ง€๋‚œ๋‚ ์˜ ์ถ”์–ต์ด..) GPT3.5-turbo ๊ธฐ์ค€ Input ํ† ํฐ ๊ฐ€๊ฒฉ์€ 1K๋‹น $0.0015์ด๋ฏ€๋กœ ํ•˜๋ฃจ์ข…์ผ ์ด๊ฒƒ์ €๊ฒƒ ๊ฐ€์ง€๊ณ  ๋†€์•„๋„ ๊ทธ๋ฆฌ ํฐ ๊ธˆ์•ก์ด ๋‚˜์˜ค์ง€ ์•Š์•˜๋‹ค. ๊ฑฑ์ •๋˜๋Š” ์‚ฌ๋žŒ์€ Notebook์— ํ•จ๊ป˜ ๋„ฃ์–ด๋‘” ์˜ˆ์ƒ๊ธˆ์•ก ํ•จ์ˆ˜๋ฅผ ์จ๋ณด์ž

๊ฒฐ๊ณผ

  • ์šฐ์„ ์€ ํ…Œ์ŠคํŠธ์…‹์˜ 5%(122๊ฐœ)๋งŒ์„ ์‚ฌ์šฉํ•ด์„œ ํ”„๋กฌํ”„ํŠธ ํ…Œ์ŠคํŠธ๋ฅผ ์ง„ํ–‰ํ–ˆ๋‹ค

  • ์ฐธ๊ณ ๋กœ ๋ฐ์ดํ„ฐ์…‹ ๋ฒค์น˜๋งˆํฌ ์„ฑ๋Šฅ์€ ์ด๋ ‡๋‹ค
                precision    recall  f1-score   support

     ์—ฌ์„ฑ/๊ฐ€์กฑ       0.85      0.70      0.76       394
         ๋‚จ์„ฑ       0.87      0.83      0.85       334
      ์„ฑ์†Œ์ˆ˜์ž       0.90      0.78      0.83       280
     ์ธ์ข…/๊ตญ์        0.87      0.79      0.82       426
         ์—ฐ๋ น       0.92      0.75      0.83       146
         ์ง€์—ญ       0.87      0.88      0.88       260
         ์ข…๊ต       0.87      0.86      0.87       290
      ๊ธฐํƒ€ํ˜์˜ค       0.92      0.18      0.30       134
     ์•…ํ”Œ/์š•์„ค       0.76      0.59      0.67       786
       clean       0.74      0.79      0.77       935

   micro avg       0.82      0.73      0.77      3985
   macro avg       0.86      0.72      0.76      3985
weighted avg       0.82      0.73      0.77      3985
 samples avg       0.76      0.74      0.75      3985
  • ์ƒ˜ํ”Œ ์ˆ˜ ์ฐจ์ด๊ฐ€ ๊ฝค ๋‚˜์ง€๋งŒ ์„ฑ๋Šฅ์ฐจ์ด๊ฐ€ ํฌ๊ฒŒ ๋‚œ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๋‚จ์„ฑ ์นดํ…Œ๊ณ ๋ฆฌ๋Š” ๋งž์ถ”๊ธฐ ์‰ฌ์šด ๊ฑด๋ฐ๋„ ์ฒ˜์ฐธํ•œ ์„ฑ๋Šฅ์„ ๋ณด์ธ๋‹ค. ์—ฌ๊ธฐ์„œ ์‚ฌ์ด์ฆˆ์—…ํ•˜๊ธฐ ์ „์— ํ”„๋กฌํ”„ํŠธ๋ฅผ ๊ฐœ์„ ํ•ด๋ณด์ž

4. ํ”„๋กฌํ”„ํŠธ ๊ฐœ์„ : ์ž„๋ฒ ๋”ฉ ์‚ฌ์šฉํ•˜๊ธฐ

  • ๋ฐฉ๊ธˆ๊นŒ์ง€ ์‚ฌ์šฉํ•˜๋˜ ํ”„๋กฌํ”„ํŠธ๋Š” ํ”„๋กฌํ”„ํŠธ์— ์˜ˆ์ œ๋ฅผ ๋„ฃ์–ด์ฃผ๊ธด ํ–ˆ์ง€๋งŒ ๋ผ๋ฒจ๋งํ•ด์•ผํ•˜๋Š” ๋ฐ์ดํ„ฐ์™€ ๊ด€๊ณ„์—†์ด ํ•ญ์ƒ ๋™์ผํ•œ ์˜ˆ์ œ์˜€๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ์ด ๋•Œ! ์ž…๋ ฅ๊ฐ’์— ๋”ฐ๋ผ ์˜ˆ์ œ๊ฐ€ ๋ณ€๊ฒฝ๋˜๋ฉด ์–ด๋–จ๊นŒ?

  • ์ด๋Ÿฐ ๊ธฐ๋Šฅ์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์ด Example Selector๋ผ๋Š” ๋žญ์ฒด์ธ์˜ ๊ธฐ๋Šฅ์ด๋‹ค

  • Example Selector๋ฅผ ์œ„ํ•ด์„œ๋Š” ํ…์ŠคํŠธ๋ฅผ ์ž„๋ฒ ๋”ฉ์œผ๋กœ ๋ณ€ํ™˜, ์—ฌ๋Ÿฌ๊ฐœ์˜ ์ž„๋ฒ ๋”ฉ ์ค‘์—์„œ ์œ ์‚ฌํ•œ ์ž„๋ฒ ๋”ฉ์„ ์ฐพ์•„๋‚ด๋Š” ๊ธฐ๋Šฅ, ๊ทธ๋ ‡๊ฒŒ ์ฐพ์•„๋‚ธ ์ž„๋ฒ ๋”ฉ์— ๋Œ€์‘ํ•˜๋Š” ์˜ˆ์ œ๋ฅผ ํ”„๋กฌํ”„ํŠธ์— ์ฃผ์ž…ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ํ•˜๋‚˜ํ•˜๋‚˜ ๊ตฌํ˜„ํ•ด์•ผํ•˜๋Š”๋ฐ ๊ทธ๋Ÿด ํ•„์š”๊ฐ€ ์—†๋Š” ์•„์ฃผ ํŽธ๋ฆฌํ•œ ๊ธฐ๋Šฅ์ด๋‹ค

  • ๊ธฐ์กด์˜ ํ”„๋กฌํ”„ํŠธ๋ฅผ ๋ณ€๊ฒฝํ•ด๋ณด์ž!

์ž„๋ฒ ๋”ฉ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ

  • ์ž„๋ฒ ๋”ฉ์€ PLM์ด๋‚˜ LLM ์ค‘ ์•„๋ฌด๊ฑฐ๋‚˜ ์‚ฌ์šฉํ•ด๋„๋œ๋‹ค. OpenAI์—์„œ๋„ ๋ฌผ๋ก  ์ง€์›ํ•ด์ฃผ๋Š”๋ฐ, ๋ฐ˜๋“œ์‹œ ์„ฑ๋Šฅ์„ ๋ณด์žฅํ•˜๋Š” ๊ฑด ์•„๋‹ˆ์—ˆ๋‹ค. ์šฐ์„ ์€ ๋ฐ์ดํ„ฐ์…‹ ๋ฒค์น˜๋งˆํฌ์—์„œ ์‚ฌ์šฉํ–ˆ๋˜ BERT ์‚ฌ์ „ํ•™์Šต ๋ชจ๋ธ์„ ํ†ตํ•ด ์ž„๋ฒ ๋”ฉ ๋ชจ๋ธ์„ ์ •์˜ํ•˜์ž
from langchain.embeddings import HuggingFaceEmbeddings
embeddings = HuggingFaceEmbeddings(
    model_name = 'smilegate-ai/kor_unsmile'# 'sentence-transformers/all-mpnet-base-v2'
) 
  • ํ˜„์žฌ ํ”„๋กฌํ”„ํŠธ ์‹คํ—˜์€ ํ…Œ์ŠคํŠธ์…‹์—์„œ ํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์‚ฌ์ „ํ•™์Šต ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•œ๋‹ค๊ณ  ํ•˜๋”๋ผ๋„ unseen data๋ผ๋Š” ์ ์„ ์ฐธ๊ณ ํ•ด๋‘์ž

์ž…๋ ฅ ํ”„๋กฌํ”„ํŠธ ๋ณ€๊ฒฝ

  • ์ง€๋‚œ๋ฒˆ๊ณผ ๋‹ฌ๋ฆฌ ์ž…๋ ฅ ํ”„๋กฌํ”„ํŠธ ๋ถ€๋ถ„์„ example_selector๋กœ ๊ต์ฒดํ–ˆ๋‹ค
# input formater

fewshot_template = """
{label_template}

{example_selector}

{format_instructions}
"""

prompt_template = ChatPromptTemplate.from_template(fewshot_template)
  • ์ž„๋ฒ ๋”ฉ์„ ํ†ตํ•ด ์ฐพ์•„๋‚ธ ์œ ์‚ฌํ•œ ์˜ˆ์ œ๋ฅผ ๋‹ด์•„๋‘˜ ํ”„๋กฌํ”„ํŠธ ํ…œํ”Œ๋ฆฟ์„ ์ •์˜ํ•ด์•ผํ•œ๋‹ค
from langchain.prompts.example_selector import MaxMarginalRelevanceExampleSelector
from langchain.vectorstores import FAISS # ๋น ๋ฅด๊ฒŒ ์œ ์‚ฌํ•œ ์ž„๋ฒ ๋”ฉ์„ ์ฐพ์•„์ฃผ๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜
from langchain.prompts import FewShotPromptTemplate, PromptTemplate
example_prompt = PromptTemplate(
    input_variables=["text", "label"],
    template='text: "{text}"\nlabel: "{label}"',
)

examples = [{'text': text, 'label': label} for text, label in zip(train_df['๋ฌธ์žฅ'].values, train_df['label'].values)]
  • ๊ทธ ๋‹ค์Œ์—” MaxMarginalRelevanceExampleSelector๋ผ๋Š” ๋ฐฉ์‹์œผ๋กœ ์–ด๋–ป๊ฒŒ ์œ ์‚ฌํ•œ ์˜ˆ์ œ๋ฅผ ์ฐพ์„ ๊ฑด์ง€ ์ •์˜ํ•  ๊ฑฐ๋‹ค. ์œ ์‚ฌํ•œ ์˜ˆ์ œ๋ฅผ ์ฐพ๋Š” ๋ฐฉ์‹์€ ๊ฐ€์žฅ ๋น„์Šทํ•œ๊ฑฐ ์ฐพ๋Š”๊ฒŒ ๊ฐ€์žฅ ๊ฐ„๋‹จํ•œ ๋ฐฉ๋ฒ•์ผํ…๋ฐ ์ด๋Ÿฌ๋ฉด ์˜ˆ์ œ์˜ ๋‹ค์–‘์„ฑ์ด ๊ฐ์†Œ๋  ์ˆ˜ ์žˆ๋‹ค, ๊ทธ๋ž˜์„œ ์–ด๋Š์ •๋„ ์œ ์‚ฌํ•œ N๊ฐœ์˜ ์˜ˆ์ œ๋ฅผ ์ฐพ์€ ๋‹ค์Œ์— ๊ทธ์ค‘์—์„œ ๋žœ๋คํ•˜๊ฒŒ ์˜ˆ์ œ๋ฅผ ์„ ํƒํ•˜๋Š” ๋ฐฉ์‹์ด๋‹ค
example_selector = MaxMarginalRelevanceExampleSelector.from_examples(
    examples,
    embeddings,
    FAISS,
    k=2, # ๋ช‡๊ฐœ์˜ ์˜ˆ์ œ๋ฅผ ๋„ฃ์„๊ฑด์ง€ ์ •ํ•ด์ค€๋‹ค
)

mmr_prompt = FewShotPromptTemplate(
    example_selector=example_selector,
    example_prompt=example_prompt,
    prefix='For example:',
    suffix='Input:\ntext:"{text}"',
    input_variables=["text"],
)

๋ชจ๋ธ ์‹คํ–‰

  • ๋น„์Šทํ•œ ๋ชจ๋ธ ์‹คํ–‰ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค์–ด ๋‹ค์‹œ ์‹คํ—˜์„ ํ•ด๋ณด์ž
def autolabel_with_embed(input_text):
    messages = prompt_template.format_messages(
        label_template=label_template,
        example_selector=mmr_prompt.format(text=input_text),
        format_instructions = format_instructions
    )
    
    response = chat(messages)
    return output_parser.parse(response.content) # {'label': 'Academic'}
    

exp2_result = []

for input_text in tqdm(test_df['๋ฌธ์žฅ'].values[len(exp2_result):]):
    exp2_result.append(autolabel_with_embed(input_text))

๊ฒฐ๊ณผ

  • ์ „๋ฐ˜์ ์œผ๋กœ ๊ฐœ์„ ๋๋‹ค! ํŒŒ์ธํŠœ๋‹ ๋ชจ๋ธ ์„ฑ๋Šฅ์— ๋น„ํ•ด์„  ๋‚ฎ์ง€๋งŒ (Macro F1=0.76) ๊ณ ์ •๋œ ํ“จ์ƒท ์˜ˆ์ œ๋ฅผ ์“ธ ๋•Œ ๋ณด๋‹ค๋Š” (Macro F1=0.42) ํ›จ์”ฌ ๋‚˜์•„์กŒ๋‹ค

ํ›„๊ธฐ

  • ํ”„๋กฌํ”„ํŠธ ์—”์ง€๋‹ˆ์–ด๋ง์ด๋ž‘ LLM ๋ฐฐ์šฐ๋ฉด์„œ ๋”๋”์šฑ ์‹ค์šฉ์ ์ธ ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ์ƒ๊ฐํ•ด๋ณด๋Š”๊ฒŒ ํ›จ์”ฌ ๋” ๋„์›€์ด ๋  ๊ฑฐ๊ฐ™์•„์„œ ์ƒ๊ฐํ•œ ํ”„๋กœ์ ํŠธ
  • ๋งˆ์ง€๋ง‰ ๊ฒฐ๊ณผ๋ฅผ ๋ณด๊ณค ํ“จ์ƒท ๋ฐฉ์‹ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ๊ธฐ๋ณธ์œผ๋กœ ์ž„๋ฒ ๋”ฉ ๋ชจ๋ธ์„ ๊ณ ๋ คํ•˜๋Š”๊ฒŒ ์ข‹์„ ๊ฑฐ ๊ฐ™๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ๋‹ค. ๋ฌผ๋ก  ๊ธ/๋ถ€์ •๊ณผ ๊ฐ™์€ ๊ฐ„๋‹จํ•œ ํ…Œ์Šคํฌ๋ผ๋ฉด ์ƒ๊ด€์—†์ง€๋งŒ ํ˜์˜คํ‘œํ˜„์ฒ˜๋Ÿผ ์‚ฌ๋žŒ๋„ ์–ด๋ ค์šด ํ…Œ์Šคํฌ๋ผ๋ฉด ๋”๋”์šฑ
  • ์˜ค๋Š˜ ๋งŒ๋“  ์˜คํ†  ๋ผ๋ฒจ๋Ÿฌ์˜ ๋ชฉ์ ์ด ํ•œ์‚ฌ๋žŒ์„ ๋Œ€์ฒดํ•˜๋Š” ๊ฑด๋ฐ API ์š”๊ธˆ์€ ๋Œ€๋žต (1๋งŒ8์ฒœ๊ฐœ์˜ ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•ด 50๋‹ฌ๋Ÿฌ ์ •๋„ ๋‚˜์˜ฌ ๊ฑฐ ๊ฐ™๋‹ค) ๊ทธ๋Ÿฐ๋ฐ ์—ฌ๊ธฐ์—์„œ ๋ผ๋ฒจ๋Ÿฌ๋ฅผ ๊ณ ์šฉํ•˜๋Š” ๊ฒƒ vs. ๊ฐœ๋ฐœ์ž๊ฐ€ ํ”„๋กฌํ”„ํŠธ ์—”์ง€๋‹ˆ์–ด๋ง ํ•˜๋ฉด์„œ ์˜คํ†  ๋ผ๋ฒจ๋Ÿฌ ๋งŒ๋“ค๊ธฐ ์ค‘์—์„œ ๋ญ๊ฐ€ ๋” ์ข‹์„์ง€ ๊ณ ๋ฏผํ•ด๋ด์•ผํ•  ๊ฑฐ ๊ฐ™๋‹ค
  • ํ…Œ์Šคํฌ๊ฐ€ ๊ฐ„๋‹จํ•œ ๊ฒฝ์šฐ ๊ฑฐ๋‚˜ ์ƒˆ๋กœ์šด ๋ผ๋ฒจ์— ๋Œ€ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๋งŒ๋“ค์–ด์•ผํ•  ํ•„์š”๊ฐ€ ์žˆ์„ ๋•Œ(์ด๊ฑด ์•ˆํ•ด๋ดค์Œ)๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์„ ๊ฑฐ ๊ฐ™์€๋ฐ, ์˜ค๋Š˜ ์‚ฌ์šฉํ–ˆ๋˜ ๋ฐ์ดํ„ฐ์ฒ˜๋Ÿผ ๋‹ค์†Œ ์„ฑ๋Šฅ์„ ์˜ฌ๋ ค์•ผํ•  ์—ฌ์ง€๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ์—” ๊ทธ๋ƒฅ ์‚ฌ๋žŒ์„ ๋” ๊ณ ์šฉํ•˜๋Š”๊ฒŒ ๋‚˜์„ ์ˆ˜๋„ ์žˆ์ง€์•Š์„๊นŒ๋ผ๋Š” ์ƒ๊ฐ์ด ๋“ค์—ˆ๋‹ค
  • ๊ฒŒ๋‹ค๊ฐ€ ๋ณต์žกํ•œ ํ…Œ์Šคํฌ๋ผ๋ฉด ์—ญ์‹œ ์‚ฌ๋žŒ ์ „๋ฌธ๊ฐ€๊ฐ€ ํ•ฉ๋ฅ˜ํ•ด์„œ ์ดˆ๊ธฐ์— ๊ฒฝํ—˜์ ์œผ๋กœ ๊ฐ€์ด๋“œ๋ผ์ธ ๊ตฌ์ถ• & ์ •์ œ ์ž‘์—…์„ ํ•ด์ค˜์•ผํ•˜๋Š”๋ฐ, ์–ธ์ œ ์ด๋Ÿฐ ์˜คํ† ๋ผ๋ฒจ๋Ÿฌ๋ฅผ ์“ฐ๋ฉด ์ข‹์„์ง€ ๊ณ ๋ฏผํ•ด๋ณผ ํ•„์š”๊ฐ€ ์žˆ๊ฒ ๋‹ค
profile
๋„ํŒŒ๋ฏผ ์ค‘๋…

0๊ฐœ์˜ ๋Œ“๊ธ€