본문 바로가기
📚도서 공부/LangChain으로 구현하는 LLM

4-2-2(정보요약, 프롬프트 템플릿, 밀도체인) Langchain 비서 구축

by Majestyblue 2024. 4. 22.

2. 정보 요약

빠르게 변화하는 요즘 환경에서는 지속적으로 증가하는 정보 양에 대응하는 것이 어렵다. 특히 컴퓨터 과학 및 AI 분야는 더욱 그렇다. 수 많은 논문을 읽고 이해하는 것에 시간이 너무 많이 소요된다. 이 때 자동화가 중요한 역할을 한다. LLM은 강력한 언어 이해 능력을 통해 텍스트를 간추리는 데 뛰어나다. LangChain을 사용해 요약 기술을 더욱 정교한 수준으로 탐색해 보자.

 

2. 프롬프트 템플릿

동적 입력에 대해 프롬프트 템플릿은 미리 정의된 프롬프트에 텍스트를 삽입할 수 있게 하여 변수 길이 제한과 모듈식 프롬프트 디자인을 허용한다.

이를 LangChain 표현 언어 LCEL(LangChain Expression Language)에서 구현할 수 있다.

from langchain.llms import GPT4All
from langchain import PromptTemplate
from langchain.schema import StrOutputParser

#위에서 선언하였음.
#model = "E:\\GPT4ALL\\Download Models\\mistral-7b-instruct-v0.2.Q4_0.gguf"
#llm = GPT4All(model=model, device='gpu')

promt = PromptTemplate.from_template(
    "Summerize this text: {text}?"
)
runnable = promt | llm | StrOutputParser()
summary = runnable.invoke({"text":text})

Pluto is a dwarf planet located in the Kuiper Belt, beyond Neptune's orbit. It is the ninth-largest and tenth-most-massive celestial body directly orbiting the Sun. Pluto has an elliptical orbit that ranges from 30 to 49 astronomical units (AU) from the Sun, taking 5.5 hours for sunlight to reach it at its farthest point. It is composed primarily of ice and rock and has five known moons: Charon, Styx, Nix, Kerberos, and Hydra. Pluto was discovered in 1930 by Clyde Tombaugh but was reclassified as a dwarf planet in 2006 by the International Astronomical Union (IAU). Despite its demotion, many astronomers still consider it a planet.

명왕성은 해왕성의 궤도 너머 카이퍼 벨트에 위치한 왜행성입니다. 명왕성은 태양의 궤도를 직접 도는 9번째로 크고 10번째로 질량이 큰 천체입니다. 명왕성은 태양으로부터 30에서 49 천문단위 (AU)에 이르는 타원형 궤도를 가지고 있으며, 태양빛이 가장 먼 지점에 도달하는 데 5.5시간이 걸립니다. 명왕성은 주로 얼음과 바위로 구성되어 있으며 카론, 스틱스, 닉스, 케르베로스, 히드라 등 다섯 개의 알려진 위성을 가지고 있습니다. 명왕성은 1930년 클라이드 톰보에 의해 발견되었지만 2006년 국제천문연맹에 의해 왜행성으로 재분류되었습니다. 명왕성의 등급이 강등되었음에도 불구하고, 많은 천문학자들은 여전히 명왕성을 행성으로 생각합니다.
  • from langchain.llms import GPT4All: langchain 라이브러리의 llms 모듈에서 GPT4All 클래스를 임포트합니다. 이 클래스는 다양한 언어 모델을 활용하기 위한 인터페이스를 제공합니다.
  • from langchain import PromptTemplate: langchain 라이브러리에서 PromptTemplate 클래스를 임포트합니다. 이 클래스는 모델에 전달할 프롬프트를 템플릿 형식으로 만들기 위해 사용됩니다.
  • from langchain.schema import StrOutputParser: langchain 라이브러리의 schema 모듈에서 StrOutputParser 클래스를 임포트합니다. 이 클래스는 모델의 출력을 문자열로 파싱하고 처리하는 데 사용됩니다.
  • promt = PromptTemplate.from_template("Summerize this text: {text}?"): PromptTemplate.from_template 메서드를 사용하여 텍스트 요약을 위한 프롬프트 템플릿을 생성합니다. {text}는 나중에 실제 텍스트로 대체될 자리 표시자입니다.
  • runnable = promt | llm | StrOutputParser(): 여기서는 파이프라인을 구성합니다. PromptTemplate 인스턴스, GPT4All 인스턴스, 그리고 StrOutputParser 인스턴스를 연결하여 입력된 텍스트를 모델에 전달하고, 모델의 출력을 문자열로 파싱하는 과정을 정의합니다.
  • summary = runnable.invoke({"text":text}): 마지막으로, 파이프라인을 실행하는 invoke 메서드를 호출합니다. text라는 키워드 인자에 실제 요약하고자 하는 텍스트를 전달합니다. 이 과정을 통해 모델은 주어진 텍스트를 요약하고, 그 결과가 summary 변수에 저장됩니다.

runnable = promt | llm | StrOutputParser() 기법은 대표적인 LCEL이며 다른 말로 ‘체인’ 이라고 한다. 찾아보니 Unix의 파이프라인 표기법과 비슷하다고 한다. 프롬프트 템플릿(promt), LLM(llm)및 출력 파서(StrOutputParser()가 서로 연결되어 있다.

 

LCEL은 코드를 직접 작성하는 것보다 직관적이고 생산적인 선언적인 체인 작성 방식을 제공한다. 비동기 처리, 배치 처리, 스티리밍, 예외 처리, 병렬 처리에 대한 내장 지원 및 LangSmith 추적과의 원활한 통합이 포함된다.

 

3. 밀도 체인

세일즈포스(Salesforce)의 여러 연구원은 GPT-4에서 생성된 요약의 정보 밀도를 점진적으로 높이면서 길이를 제어하기 위해 밀도 체인(CoD, Chain of Density)라는 프롬프트 지도(prompt-guided)기술을 개발했다.

[2309.04269] From Sparse to Dense: GPT-4 Summarization with Chain of Density Prompting (arxiv.org)

 

From Sparse to Dense: GPT-4 Summarization with Chain of Density Prompting

Selecting the ``right'' amount of information to include in a summary is a difficult task. A good summary should be detailed and entity-centric without being overly dense and hard to follow. To better understand this tradeoff, we solicit increasingly dense

arxiv.org

번역하면 다음과 같다.

    """
    Article: {article}
You will generate increasingly concise, entity-dense summaries of the above article. 

Repeat the following 2 steps 5 times. 

Step 1. Identify 1-3 informative entities (";" delimited) from the article which are missing from the previously generated summary. 
Step 2. Write a new, denser summary of identical length which covers every entity and detail from the previous summary plus the missing entities. 

A missing entity is:
- relevant to the main story, 
- specific yet concise (5 words or fewer), 
- novel (not in the previous summary), 
- faithful (present in the article), 
- anywhere (can be located anywhere in the article).

Guidelines:

- The first summary should be long (4-5 sentences, ~80 words) yet highly non-specific, containing little information beyond the entities marked as missing. Use overly verbose language and fillers (e.g., "this article discusses") to reach ~80 words.
- Make every word count: rewrite the previous summary to improve flow and make space for additional entities.
- Make space with fusion, compression, and removal of uninformative phrases like "the article discusses".
- The summaries should become highly dense and concise yet self-contained, i.e., easily understood without the article. 
- Missing entities can appear anywhere in the new summary.
- Never drop entities from the previous summary. If space cannot be made, add fewer new entities. 

Remember, use the exact same number of words for each summary.
Answer in JSON. The JSON should be a list (length 5) of dictionaries whose keys are "Missing_Entities" and "Denser_Summary".
"""

<번역본>
조문 : {{조문}}
위의 기사에 대해 점점 더 간결하고 기업 밀도가 높은 요약을 생성하게 됩니다. 

다음 2단계를 5회 반복합니다. 

1단계. 이전에 생성된 요약에서 누락된 기사에서 1-3개의 정보 개체(";" 구분됨")를 식별합니다. 
2단계. 이전 요약의 모든 개체 및 세부 정보와 누락된 개체를 포함하는 동일한 길이의 새롭고 밀도 높은 요약을 작성합니다. 

누락된 개체는 다음과 같습니다:
- 주요 내용과 관련이 있습니다, 
- 구체적이면서도 간결한(5단어 이하), 
- 소설(이전 요약에 없음), 
- 충실한(기사에 있음), 
- 어디든지(기사 내 어디든지).

지침:

- 첫 번째 요약은 길지만(4-5문장, ~80단어) 매우 구체적이지 않으며 누락된 것으로 표시된 개체 이외의 정보는 거의 포함되지 않습니다. ~80단어에 도달하려면 지나치게 장황한 언어와 필터(예: "이 기사에서 설명")를 사용하십시오.
- 모든 단어를 카운트합니다. 이전 요약을 다시 작성하여 흐름을 개선하고 추가 개체를 위한 공간을 만듭니다.
- "기사는 논한다"와 같은 유익하지 않은 문구를 융합, 압축 및 제거하여 공간을 만듭니다.
- 요약은 매우 조밀하고 간결하면서도 자체적으로 구성되어야 합니다. 즉, 기사 없이도 쉽게 이해할 수 있습니다. 
- 누락된 엔티티는 새 요약의 어느 곳에나 나타날 수 있습니다.
- 이전 요약에서 도면요소를 삭제하지 마십시오. 공백을 만들 수 없는 경우 새 도면요소를 더 적게 추가하십시오. 

각 요약에 정확히 동일한 수의 단어를 사용해야 합니다.
JSON으로 답하십시오. JSON은 "Missing_Entities" 및 "Denser_Summary" 키를 가진 사전 목록(길이 5)이어야 합니다.

CoD 프롬프트는 GPT-4에 기사의 초기 희소하고 상세한 요약을 생성하도록 지시한다. 몇 개의 개체만 포함되는데 반복적으로 1~3개의 누락된 개체를 식별하고 이를 이전 요약과 동일한 단어 수로 다시 작성한다. 이러한 반복적인 재작성은 추상화 증가, 세부 사항의 융합, 각 단계에서의 추가적 개체를 만들기 위해 압축을 강제한다. 5번의 반복 끝에 요약은 창의적인 재작성을 통해 토큰당 더 많은 개체가 포함된 고밀도로 압축된 형태가 된다고 한다.

 

한번 시도해 보았다.

#위에서 선언하였음.
#model = "E:\\GPT4ALL\\Download Models\\mistral-7b-instruct-v0.2.Q4_0.gguf"
#llm = GPT4All(model=model, device='gpu')

promt = PromptTemplate.from_template(
    """
    Article: {article}
You will generate increasingly concise, entity-dense summaries of the above article. 

Repeat the following 2 steps 5 times. 

Step 1. Identify 1-3 informative entities (";" delimited) from the article which are missing from the previously generated summary. 
Step 2. Write a new, denser summary of identical length which covers every entity and detail from the previous summary plus the missing entities. 

A missing entity is:
- relevant to the main story, 
- specific yet concise (5 words or fewer), 
- novel (not in the previous summary), 
- faithful (present in the article), 
- anywhere (can be located anywhere in the article).

Guidelines:

- The first summary should be long (4-5 sentences, ~80 words) yet highly non-specific, containing little information beyond the entities marked as missing. Use overly verbose language and fillers (e.g., "this article discusses") to reach ~80 words.
- Make every word count: rewrite the previous summary to improve flow and make space for additional entities.
- Make space with fusion, compression, and removal of uninformative phrases like "the article discusses".
- The summaries should become highly dense and concise yet self-contained, i.e., easily understood without the article. 
- Missing entities can appear anywhere in the new summary.
- Never drop entities from the previous summary. If space cannot be made, add fewer new entities. 

Remember, use the exact same number of words for each summary.
Answer in JSON. The JSON should be a list (length 5) of dictionaries whose keys are "Missing_Entities" and "Denser_Summary".
"""
)
runnable = promt | llm | StrOutputParser()
summary = runnable.invoke({"article":text})
print(summary)
[{
    "Missing_Entities": ["Pluto's five known moons: Charon, Styx; Nix; Kerberos; Hydra"],
    "Denser_Summary": "Pluto is a dwarf planet in the Kuiper belt with five known moons: Charon, Styx, Nix, Kerberos, and Hydra."
}, {
    "Missing_Entities": ["Pluto's discovery by Clyde W. Tombaugh"],
    "Denser_Summary": "Discovered in 1930 by Clyde W. Tombaugh, Pluto is a dwarf planet with five known moons: Charon, Styx, Nix, Kerberos, and Hydra."
}, {
    "Missing_Entities": ["Pluto's orbit"],
    "Denser_Summary": "Pluto, discovered in 1930 by Clyde W. Tombaugh, is a dwarf planet with five known moons: Charon, Styx, Nix, Kerberos, and Hydra, located in the Kuiper belt with an ecc
    
    [{
"Missing_Entities": ["플루토의 다섯 위성 카론, 스틱스, 닉스, 케르베로스, 히드라"],
"Denser_Summary": "플루토는 카이퍼 벨트에 있는, 카론, 스틱스, 닉스, 케르베로스, 히드라 등 다섯 개의 알려진 위성을 가진 왜행성입니다."
}, {
"Missing_Entities": ["클라이드 W. 톰보의 플루토의 발견"],
"Denser_Summary": "클라이드 톰보(Clyde W. Tombaugh)가 1930년에 발견한 명왕성은 카론(Charon), 스틱스(Styx), 닉스(Nix), 케르베로스(Kerberos), 히드라(Hydra) 등 다섯 개의 알려진 위성을 가진 왜행성입니다."
}, {
"Missing_Entities": ["Pluto's orbit"],
"Denser_Summary": "Clyde W. Tombaugh에 의해 1930년에 발견된 플루토는 카론, 스틱스, 닉스, 케르베로스, 히드라 등 다섯 개의 알려진 위성을 가진 왜행성입니다

 

생각보다 잘 안되는데요? 후기에 의하면 GPT-4만 잘 되는 듯 하다.

From Sparse to Dense: GPT-4 Summarization with Chain of Density Prompting : r/LangChain (reddit.com)

 

From the LangChain community on Reddit: From Sparse to Dense: GPT-4 Summarization with Chain of Density Prompting

Explore this post and more from the LangChain community

www.reddit.com