LangchainJS 리뷰 #1

최근 뉴스에 자주 등장하는 langchain의 Model, Prompt, Indexing 대해 살펴 봅니다.

2023-07-02

소개

Getting Started with GPT-3 vs. Open Source LLMs - LangChain #1 - YouTube

4개의 주요 컴포넌트

  • Prompt templates: LLM의 미션과 질의/응답의 형태를 정의
  • LLMs: GPT-3, BLOOM 등
  • Agent: 웹 검색, 계산기 등
  • Memory: short-term, long-term 저장소

Prompt Templates for GPT 3.5 and other LLMs - LangChain #2 - YouTube

Prompt template 기능을 사용하여 일반적인 질문, few shot running 등을 손쉽게할 수 있습니다.

LLMs

일단 langchain으로 활용할 수 있는 LLM이 궁금할 것 입니다. 다음의 위치에서 지원하는 LLM들의 구현체를 확인할 수 있습니다.

langchainjs/langchain/src/llms at main · hwchase17/langchainjs · GitHub

@huggingface/inference - npm

Huggingface의 경우 huggingface inference API를 사용하여 응답을 주고 받습니다.

Prompts

Prompt templates

Prompt Templates | 🦜️🔗 Langchain

이해할 수 없을 정도로 다소 복잡한 구조를 가지고 있습니다.

근본적으로는 string 형태를 반환하는 template 유틸리티 함수들 입니다.

Chat 요소를 담아내기 위해 chat 형식(사람, 시스템, AI 인지 등을 구분), chat 이름등의 정보를 담을 수 있습니다.

PipelinePromptTemplate을 사용하여 템플릿을 조합할 수 있습니다.

결국 string 형태의 출력물을 얻게되는데요. 다소 over engineering이 아닌가 생각합니다. 아무래도 python과 호환을 위해 기계적으로 대응하는 클래스를 구현한 듯 한데요. JavaScript 에서는 string template이 있기 때문에 상대적으로 한눈에 이해하기 어려운 구조를 가지고 있습니다.

물론 template을 serialize 해서 이 기종간에 혹은 타 언어간에 전달하여 활용할 수도 있겠습니다. 하지만, 당장 저에겐 그로인한 장점이 보이지는 않습니다. 오히려 propmt template을 정의하는 선언적 DSL을 만드는 것이 요즘 추세에 적합해 보입니다.

format 함수는 string을 반환하고 formatPromptValue 함수는 PromptValue를 반환합니다. PromptValue는 필요할 때 string이나 ChatMessage 형식으로 변환할 수 있습니다.

partial 함수를 사용해 템플릿의 특정 변수를 치환할 수 있습니다.

FewShotPromptTemplate을 활용하여 여러 예시를 학습 정보로 전달하는 few shot learning을 할 수 있습니다.

Output parser

Output Parsers | 🦜️🔗 Langchain

프롬프트를 사용하여 질문에 대한 답의 형식을 요구할 수 있습니다.

StructuredOutputParser는 json 형식으로 답을 요구하는 프롬프트를 생성합니다. JSON 형식에 대한 요구사항을 JSON schema로 설명하는 프롬프트를 LLM의 입력으로 전달하면 string으로 된 JSON 응답을 받습니다. 이 응답을 StructuredOutputParser 인스턴스를 사용하여 파싱을 하면 원하는 JSON 객체를 얻을 수 있습니다.

Example selector

Example Selectors | 🦜️🔗 Langchain

LengthBasedExampleSelector는 예제를 포함한 프롬프트 문구의 길이를 제한하는 기능을 가지고 있습니다. 많은 예시를 입력하더라도 설정한 길이를 넘지 않도록 프롬프트를 생성합니다.

SemanticSimilarityExampleSelectorEmbeddings 인스턴스를 전달하여 예제와 inputVariables의 입력값과 유사한 예시를 선택하여 프롬프트를 생성합니다. 이 과정에서 embedding API 호출로 인한 과금이 발생할 수 있습니다.

Indexes

Document Loaders

Node.js 환경에서 CSV, Docx, Epub, JSON, PDF 등의 파일을 읽어올 수 있습니다.

또한, Cheerio, Puppeteer, Playwright를 활용한 web page 클롤링, Gitbook, Github repo, S3 파일과 같이 리모트에 존재하는 문서를 읽어올 수 있습니다.

Text splitters

읽어온 문서를 적절히 LLM의 최대 문서 전송 크그에 맞추어 나누어주는 기능을 제공합니다.

RecursiveCharacterTextSplitter는 텍스트 문서를 나눕니다. RecursiveCharacterTextSplitter.fromLanguage 함수는 특정 언어의 코드를 나누는 역할을 합니다. TokenTextSplitter는 텍스트를 BPE로 변환한 뒤 문서를 나눕니다.

Byte Pair Encoding - ratsgo's NLPBOOK

chunkHeaderOptions은 여러 문서에서 정보를 가져올 때, 어떤 문서인지 구분하는데 유용합니다.

Vector stores

embedding 후의 벡터 정보를 저장하는 기능 입니다.

Node.js 만으로 사용하고 싶다면, HNSWLib, Faiss, LanceDB를 사용합니다. 브라우저와 같은 환경에서 활용가능한 메모리 기반의 저장소는 MemoryVectorStore를 사용합니다. 다양한 기능을 가지는 오픈소스 Chroma는 도커를 활용해 연동할 수 있습니다. Weaviate는 오픈소스 또는 호스팅 서비스로 사용할 수 있습니다. 그 밖에 Supabase, Pinecone, SingleStore를 사용할 수 있습니다.

Retrievers

문서의 정보를 바탕으로 구축한 vector store에 대하여 질의하기 위한 기능입니다.

Vector store는 고유한 쿼리 언어를 사용해 질의를 해야 합니다.

Retriever는 자연어로 부터 vector store가 이해할 수 있는 정형화한 질의 구문을 생성하는 프롬프트를 LLM에 전달하고 그 응답을 파싱하는 역할을 합니다.

이를 위해 다음과 같은 프롬프트를 주입합니다.

export const DEFAULT_SCHEMA = `\
<< Structured Request Schema >>
When responding use a markdown code snippet with a JSON object formatted in the \
following schema:

\`\`\`json
{{{{
    "query": string \\ text string to compare to document contents
    "filter": string \\ logical condition statement for filtering documents
}}}}
\`\`\`

The query string should contain only text that is expected to match the contents of \
documents. Any conditions in the filter should not be mentioned in the query as well.

A logical condition statement is composed of one or more comparison and logical \
operation statements.

A comparison statement takes the form: \`comp(attr, val)\`:
- \`comp\` ({allowed_comparators}): comparator
- \`attr\` (string):  name of attribute to apply the comparison to
- \`val\` (string): is the comparison value

A logical operation statement takes the form \`op(statement1, statement2, ...)\`:
- \`op\` ({allowed_operators}): logical operator
- \`statement1\`, \`statement2\`, ... (comparison statements or logical operation \
statements): one or more statements to apply the operation to

Make sure that you only use the comparators and logical operators listed above and \
no others.
Make sure that filters only refer to attributes that exist in the data source.
Make sure that filters take into account the descriptions of attributes and only make \
comparisons that are feasible given the type of data being stored.
Make sure that filters are only used as needed. If there are no filters that should be \
applied return "NO_FILTER" for the filter value.\
`;

마치며

Langchain JS에 대해서 개괄적인 정보를 모아보고 특정 시나리오를 분석해 보았습니다.

가이드 문서에 따라 Model, Prompt, Indexing에 대해서 살펴 보았습니다.

다음에는 가이드의 나머지 부분을 차례로 리뷰할 예정입니다.

Loading script...