728x90

Ollama + Langchain

 Local llm์˜ ์„ฑ๋Šฅ์ด ๋‚˜๋‚ ์ด ์ข‹์•„์ง€๋ฉฐ ์ด์ œ๋Š” 8b์ด์ƒ์˜ ๋ชจ๋ธ ์ •๋„๋ฉด ํ•œ๊ตญ์–ด instruction์ด ์ž˜๋˜์–ด CoT๋ฅผ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ๋‹ค. ๊ฐ„๋‹จํ•œ ์˜ˆ์ œ๋ฅผ ํ†ตํ•ด ์ด๋ฆฌ๋กœ ์ €๋ฆฌ๋กœ ํŠ€๋˜ LLM์„ ์–ด๋–ป๊ฒŒ ์ œ์–ดํ•˜๋Š” ์ง€ ์•Œ์•„๋ณด์ž. 

 

Mad llama

 

 

1.  Ollama cpp ๋ชจ๋ธ ์ค‘ ์ตœ๊ทผ์— ๊ณต๊ฐœ๋œ Gemma2 ์‚ฌ์šฉ

gemma2 ollama

 gemma2 ๋ชจ๋ธ ์ค‘ ๊ธฐ๋ณธ ๋ชจ๋ธ์€ 9b ๋ชจ๋ธ๋กœ google์—์„œ ๋งŒ๋“  gemma์˜ ๋ฒ„์ „ 2์ธ open source llm์ด๋‹ค. ํ•œ๊ตญ์–ด๋„ ์ž˜ํ•ด์„œ ๋ช‡ ์•ˆ๋˜๋Š”  ํ•œ๊ตญ์–ด ์˜คํ”ˆ Foundation ๋ชจ๋ธ์ด๋‹ค. google ๋ชจ๋ธ์˜ ํŠน์ง•์ด Markdown์œผ๋กœ output์„ ๋ฐ›์•„ ์›ํ•˜๋Š” ํ˜•ํƒœ๋กœ ๋” ๋„“๊ฒŒ ๊ฐ€๊ณตํ•ด ๋ฐ›์„ ์ˆ˜์žˆ๋‹ค.  

    from langchain_community.llms import Ollama
    ollama = Ollama(model="gemma2:latest",temperature=0, verbose=True)

 

 

2. Langchain์˜ BooleanOutputParser

 Langchain์˜ Outputparser๋ฅผ ํ†ตํ•ด Prompt์˜ ๋‹ต๋ณ€ Type์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค. 

 

BooleanOutputParser
class BooleanOutputParser(BaseOutputParser[bool]):
    """Parse the output of an LLM call to a boolean."""

    true_val: str = "YES"
    """The string value that should be parsed as True."""
    false_val: str = "NO"
    """The string value that should be parsed as False."""

    def parse(self, text: str) -> bool:
        """Parse the output of an LLM call to a boolean.

        Args:
            text: output of a language model

        Returns:
            boolean
        """
        regexp = rf"\b({self.true_val}|{self.false_val})\b"

        truthy = {
            val.upper()
            for val in re.findall(regexp, text, flags=re.IGNORECASE | re.MULTILINE)
        }
        if self.true_val.upper() in truthy:
            if self.false_val.upper() in truthy:
                raise ValueError(
                    f"Ambiguous response. Both {self.true_val} and {self.false_val} "
                    f"in received: {text}."
                )
            return True
        elif self.false_val.upper() in truthy:
            if self.true_val.upper() in truthy:
                raise ValueError(
                    f"Ambiguous response. Both {self.true_val} and {self.false_val} "
                    f"in received: {text}."
                )
            return False
        raise ValueError(
            f"BooleanOutputParser expected output value to include either "
            f"{self.true_val} or {self.false_val}. Received {text}."
        )

    @property
    def _type(self) -> str:
        """Snake-case string identifier for an output parser type."""
        return "boolean_output_parser"

 

 Parser์˜ Class๋ฅผ ๋ณด๋ฉด Yesy / No๊ฐ€ prompt ๊ฒฐ๊ณผ์— ์žˆ์œผ๋ฉด boolean์œผ๋กœ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ”๊ฟ” ์ค€๋‹ค. Booleanparser๋ผ๊ณ  ๋‹ต๋ณ€์„ True / False๋กœ ๋ฐ›๊ฒŒ ํ•˜๋ฉด ์•ˆ๋œ๋‹ค.. 

 


Result

 ๋‚ด๊ฐ€ ๋ฐ›์€ ์ŠคํŒธ ๋ฉ”์„ธ์ง€๋ฅผ ์ง์ ‘ ํ…Œ์ŠคํŠธ ํ•ด๋ณด์•˜๋‹ค. ์•„๋ž˜ While loop๋ฅผ ์‚ฌ์šฉํ•ด llm์ด ์ž˜๋ชป๋œ ๋‹ต๋ณ€์œผ๋กœ Booleanparser๊ฐ€ Error๋‚˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•  ์ˆ˜์žˆ๋‹ค. ollama๋ฅผ ํ†ตํ•ด llm์„ ์‰ฝ๊ฒŒ ์ธํผ๋Ÿฐ์Šคํ•˜๊ณ  langchain์œผ๋กœ ๋‚ด๊ฐ€ ์›ํ•˜๋Š” output์œผ๋กœ ํ•จ์ˆ˜ํ™” ํ•  ์ˆ˜ ์žˆ์–ด ๋งŽ์€ ๊ฒƒ์„ ์ž๋™ํ™” ํ•  ์ˆ˜์žˆ๋‹ค.

 ๋ณต์žกํ•˜์ง€๋งŒ ์ค‘์š”ํ•˜์ง€ ์•Š์€ ๊ฒƒ๋“ค์„ ๋Œ€์ƒ์œผ๋กœ ํ™œ์šฉํ•˜๊ธธ ์ถ”์ฒœํ•œ๋‹ค. ๊ทธ ์ด์œ ๋Š” GPT-4, SOTA LLM ๋ชจ๋ธ๋„ 100% ์ผ๊ด€๋˜๊ณ  ์ •ํ™•ํ•œ ๋‹ต๋ณ€์„ ๋‚ด์ง€ ์•Š๋Š”๋‹ค. 

from langchain_community.llms import Ollama
from langchain.output_parsers import BooleanOutputParser
from langchain_core.prompts import PromptTemplate

prompt = PromptTemplate(
        template=
        "Following are the questions to determine if the message is spam or not.\n"
        "Does this message contain words such as stock, share price, investment, profit, surge, buy, sell?\n"
        "Does this message guarantee high returns or promise quick investment profits?\n"
        "Does this message urge immediate buying or investment?\n"
        "Is this message sent from an untrusted source or using a suspicious email address?\n"
        "Does this message contain spam-like phrases such as 'urgent', 'exclusive', 'guaranteed profit', 'insider information'\n?"
        "If you think this message is one of the spam messages, please answer `Yes`.\n"
        "If you think this message is not a spam message, please answer `No`.\n"
        "{message}",
        input_variables=["message"],
        partial_variables={"format_instructions": format_instructions},
    )
ollama = Ollama(model="gemma2:latest",temperature=0, verbose=True)
chain = (
    prompt | ollama | BooleanOutputParser()
)
text = """
[Web๋ฐœ์‹ ]
Chat GPT AI๊ฐ€ ์ถ”์ฒœํ•˜๋Š” ์ฃผ์‹ ์„ ์ • ์ „๋žต์— ์ฐธ์—ฌํ•˜์„ธ์š”.

ํˆฌ์ž ์—ฌ์ •์„ ์‹œ์ž‘ํ•˜๊ณ  ์‹ถ์œผ์‹œ๋‹ค๋ฉด ์•„๋ž˜ ๋งํฌ๋ฅผ ํด๋ฆญํ•˜์—ฌ 
๋งค์›” 5 ๊ฐœ! ์ข…๋ชฉ๊ณผ ์ฃผ์‹ ์ „๋ฌธ ์„ ์ • ์ „๋žต์„ ๋ฌด๋ฃŒ๋กœ ๋ฐ›์•„๋ณด์„ธ์š”.

https://band.us/n/a

์ €ํฌ๋Š” ๋ฐ˜ ๋…„๋งŒ์— โ€˜โ€™1227%โ€˜โ€™ ๋ผ๋Š” ๋†€๋ผ์šด ์ˆ˜์ต์„ ์–ป์—ˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์ˆซ์ž๊ฐ€ ์•„๋‹ˆ๋ผ ์ €ํฌ๊ฐ€ ํˆฌ์ž ์ž ์žฌ๋ ฅ์— ๋Œ€ํ•œ ๊ฐ•๋ ฅํ•œ ๋ฏฟ์Œ๊ณผ ์•ฝ์† ์ž…๋‹ˆ๋‹ค.

์—ฌ๋Ÿฌ๋ถ„๋“ค์ด ์ „๋ฌธ ์ ์œผ๋กœ ์ฃผ์‹ ํˆฌ์ž๋ฅผ ํ• ์ˆ˜ ์žˆ๋„๋ก ์ตœ์„ ๋‹คํ•ด ๋„์™€ ๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค.
"""

result = chain.invoke(text)
result # True

 

  ์•ž์œผ๋กœ ์ŠคํŒธ ์ž๋™ ์‹ ๊ณ  ๋ฐฐ์น˜๋ฅผ ๋งŒ๋“ค ๊ณ„ํš์ด๋‹ค. 

๋ฐ˜์‘ํ˜•
๋‹คํ–ˆ๋‹ค