Галоўная / Артыкулы / Ручна створаная петля адынства LangChain для порэўнення паказначых жывога запасу

Ручна створаная петля адынства LangChain для порэўнення паказначых жывога запасу

Створыце паэтапна маленькі асистент для порэванавання акцыяў на базе LangChain і вы якраз разумеце цикл стварэння, прыўязкі, вызову і выканання, який дазволяе LLM запрашваць актуальныя даны замест таго, каб прасіць на адгадванне.

1667 слоў

Модель мовы знае толькі тое, што ў яе навчальных данных, таму запит пра ціну акцій на сьогодні дае толькі упэўненую дагадку, а не факт. Гэта стварае серьзёзную проблему для фінансавых запытанняў. Інструмент, які выкарыстоўвае вызыванне моделі, рашае гэту проблему, дазволяючы моделі запрашаць ваш код на загледжэнне актуальных дадзеных, а пасля аналізаваць рэзультат. У гэтым кераванні ствараецца компактны асистэнт, які порыхвае два акціі за ценай і коефіцыентам P/E, а па дорозе чыста паказвае кожны этап рабочага процесу вызывання інструментаў у LangChain: стварэнне, прыяўленне, вызыванне, выконанне.

Чаму модель без інструментаў толькі дагадваецца

Уявіце сабе працавніка магазіна, які запамятавае кожны продукт і правілы, але не мае доступу да системы запасоў. Якшто запытаць, чый ёсць паджак у середнім размере, я он тады дае упэўненую адказ на аднойчы з мінулога тыдня. Гэта і є LLM сама по сабе: яна можа выражацца, але не ўсведамляеся пра тэкстуючую рэальнасць.

Дайце партнеру сканер штрих-кодава, і ён будзе перакантраваць інфармацыю замест тагадвання. У LangChain сканер ёсць інструментам: звычная функцыя, якую модель можа запрашваць да выканання, напрыклад, для пошуку цены, запыту да базы дадзеных або вызову API. Механізм вызову інструментам дазваляе модэлі выбраць, калі трэба вжыць сканер, які элемент сканаваць і як адпрацоўваць отрыманыя данні.

Чатыроэтапны цикл

Вызов інструментам (часта называемы вызовам функцыі) завжды выконваецца за аднаковым цыклам:

  1. Створыце інструментам. Напісце функцыю на Python з описавальным іменем, параметрамі з адпаведнымі типамі і докстрынгам, які поясняе ўсё, што яна робіць.
  2. Прыўяжыце яе да модэлі. Выкличце .bind_tools() у чат-модэлі, каб яна знала, якія інструментам існуюць і якія аргументы яны прыймаюць.
  • Актывацыя модэлі. Адправляйце запит корыстніка. Якщо для адказу трэбуюцься даны з вантажнага календаря, модэль вяртае структураваны запит, напрыклад "call get_stock_price with ticker='MSFT'", заместо фінальнага адказу.
  • Выкананне і вярнэнне рэзультатаў. Ваш код запускае запрошаную функцыю і перадае выходны данні назад модэлі, каб тая могла складаць адказ.
  • Важным аспектам являецца тое, што модель, а не ваш код, выбірае, калі патрэбна якась засоба. На такыя запитанні, як "Скількі будзе 2+2?", адпаведна адказ даёцца безпосередзя, тады як запитанне "Пораўняй MSFT і AAPL" можа прызвесці да двух вызоваў засобаў у адной адказе. Модель толькі запрашае выкананне эых вызоваў; ўпэўненасць у ўсуненні прычын, якія гэтыя вызовы не могуць выкарыстацца, залишаецца вашай задачай. Як фрэймворкі автаматызуюць гэты цикл, дакладна пісана ў стацыі пра тое, што на самай працэ ЛангЧейн автаматызуе, калі вы створылі цикл агента.

    Шаг 1: Установіце залежнасці пад час першага запуску

    Скрыпт спачатку пераглядае сваія пакеты і інсталюе тыя, якія не ўсё ў наявнасці, каб хтось могаў запусканы яго без аддзельнага крока pip install. Ён ператварае назву кожнага пакета на назву для імпорту, заменяючы гілкі на апострыфы (langchain-groq стае langchain_groq), а якщо гэта не дапамагае, выкарыстоўвае pip через чырвонуюяшчык:

    import sys
    import subprocess
    
    required_packages = ["langchain-groq", "langchain-core", "yfinance"]
    
    for package in required_packages:
        try:
            __import__(package.replace("-", "_"))
        except ImportError:
            print(f"📦 Package '{package}' not found. Installing now...")
            subprocess.check_call([sys.executable, "-m", "pip", "install", package])
    

    Гэта падходзіць для дамаў, але справжнія проекты должны задаць залежнасці ў файле requirements.txt або pyproject.toml; інсталляцыя пад час выканання робіць процес будовы неперадавальным.

    Крок 2: Аддаць ключ API

    Модель працуе на Groq, таму кліент Groq патрэбуе ключ API ў сераўысі. У даме ён прызначаецца як мескальнік:

    import os
    os.environ["GROQ_API_KEY"] = "Your-API"
    

    Справжнія ключы павінны знаходзіцца ў файле .env, які не включаецца ў кантроль версій, або ў менеджере секрэтнаў, ніколі не ў кодзе, які зберагаецца.

    Шаг 3: Адактуванне інструмента для даных акцыяў

    Інструмент выкарыстоўвае yfinance для пошуку індэкса акцыі, аблекчэння найновейшай цены закрыцця за адзін дзень з історыі, а таксама чытання рыночнай капіталізацыі і коефіцыента P/E з інформацыі пра акцыю:

    from langchain_core.tools import tool
    import yfinance as yf
    
    @tool
    def get_stock_price(ticker: str) -> str:
        """Fetches the current stock price and key statistics for a given ticker symbol."""
        try:
            stock = yf.Ticker(ticker)
            todays_data = stock.history(period='1d')
            if todays_data.empty:
                return f"Could not find data for ticker {ticker}."
    
            price = todays_data['Close'].iloc[-1]
            info = stock.info
            market_cap = info.get('marketCap', 'N/A')
            pe_ratio = info.get('trailingPE', 'N/A')
    
            return f"{ticker} Current Price: ${price:.2f}, Market Cap: {market_cap}, P/E Ratio: {pe_ratio}"
        except Exception as e:
            return f"Error fetching data for {ticker}: {str(e)}"
    

    Тры аспекты робяць гэты функцыю хорашым інструментам:

    • Декоратар @tool ператварае функцыю на інструмент LangChain і вырахоўвае схему вхідных дадзеных на аднойчынку з ўказаннямі яе типа.
    • Докстрынг не ўважаецца декоратарам. Модель чытае яго разам з назвай, каб выявіць, калі трэба застосаваць інструмент; таму ў яму павінна чытка працэсавацца інформацыя пра тое, што вяртае інструмент.
    • Падчас выканання выкарыстоўваюцься описавальныя строкі замест абэктных выключэнняў. Невядомы індэкс акцыі або непаспелы запрос прыводзяць да паведамлення, якое модель можа аналізаваць (“не удалося знайсці даныя”), а не да выключэння, якое зупіняе весь процес.

    Заўважкі: yfinance — гэта неофіцыйны кэшаўчык дадзеных Yahoo Finance: данні могу быць з адзінчынай запаздаленасцю, а дэтыялі можа бракаваць, таму і викорыстоўваюцца значэння 'N/A'.

    Шаг 4: Стварыце модэль і прыўяжыце інструменты

    Далей ствараецца модэль чату, а да яе прыўязываецца спіс інструментаў:

    from langchain_groq import ChatGroq
    
    llm = ChatGroq(
        model="openai/gpt-oss-120b",
        temperature=0
    )
    
    tools = [get_stock_price]
    llm_with_tools = llm.bind_tools(tools)
    

    bind_tools() з кожным запитам адправляе модэлю назвы інструментаў, ўпісы пра яех і схемы аргументаў, ўжо таму модэль ведае, што можа запытаць. Заўважкі: непрыўязаны llm таксама застаецца; яго празначаюць пазней для стварэння фінальнага апускання. Назва модэлі паслядуе таму, што пры напісанні прастаўала Groq, таму перад запускам пераканайцеся ў актуальным спісе модэляў адпаведнага прадаўцы.

    Установка temperature=0 дапамагае падтрымваць сфармаваны і аднаковы выхід, хоць гэта скарочвае атмальнасць, але не гарантуе ідэнтычных адпаведзей.

    Шаг 5: Стварыце ланцуг запросаў

    Шаблон запросу падае інструкцыю для системы і включае запит пользователя ў паведамленне для чалавека. Пасля таго аператар “|” з’еднае запрос і модель, яка розумее інструменты, у аднае виконвальнае цэласць, падобна да каналу Unix:

    from langchain_core.prompts import ChatPromptTemplate
    from IPython.display import display, Markdown
    
    prompt = ChatPromptTemplate.from_messages([
        ("system", "You are an expert financial analyst. Use the tools provided to pull real-time data before comparing or concluding."),
        ("human", "{input}")
    ])
    
    chain = prompt | llm_with_tools
    

    Сюды саме паведамленне для системы выконвае рэальную работу: яно прасіць модель запрашваць даныя за дапамою інструментаў прытымкі робіць жадныя порэванні. Без яго модель можа даць адказ на базе застарэлых дадзеных трэніравання.

    Шаг 6: Адкрываць цыкл і обрабоцваць калькі запытанняў да інструментаў

    Галоўны блок з’еднае ўсё разам. Ён запускае ланцюг, пераказваецца, чы рэспонс заносі tool_calls, адкрывае кожны запрашаны пошук, збірае выходы і нарэшце прасіць чыстую модель напісаць порэванне на аднойчы зазначаных дадзеных. Якщо інструменты не былі запрашаны, ён выдрукавае прямой адказ модель:

    if __name__ == "__main__":
        query = "Compare the current stock price and P/E ratio of Microsoft (MSFT) AND Apple (AAPL). Which one looks cheaper based on P/E?"
        print(f"🚀 Invoking Financial Pipeline with query: '{query}'\n")
    
        # 1. Ask the model what tools it wants to use
        ai_message = chain.invoke({"input": query})
    
        # 2. Check if the model requested tool use
        if ai_message.tool_calls:
            print(f"🛠️ Model requesting {len(ai_message.tool_calls)} real-time tool lookups...\n")
            tool_outputs = []
    
            # 3. Execute ALL generated tool calls
            for tool_call in ai_message.tool_calls:
                if tool_call["name"] == "get_stock_price":
                    ticker_symbol = tool_call["args"]["ticker"]
                    print(f"   -> Executing tool lookup for: {ticker_symbol}")
    
                    result = get_stock_price.invoke(tool_call["args"])
                    print(f"      [Tool Output] {result}")
                    tool_outputs.append(result)
    
            # 4. Supply the full collective data back to the LLM
            summary_prompt = f"""
            User Query: {query}
            Real-time Data Harvested: {'; '.join(tool_outputs)}
    
            Synthesize a final response evaluating which asset looks cheaper.
            """
            final_answer = llm.invoke(summary_prompt)
    
            print("\n--- Final Analysis Output ---")
            display(Markdown(final_answer.content))
        else:
            print("\n--- Final Analysis Output ---")
            print(ai_message.content)
    

    Для запита, які стосуецца як Microsoft, так і Apple, модель зазвычай вяртае два вызовы інструментаў у адной адпаведзі, по аднаму на кожны тыкер. Цикл выкананае ўсія іх першы чым працаваць далей, таму ў пасляпэльным кроцы можна адразу бачыць оба наборы цэфраў. Модель запрашае вызовы паралельна, але гэты код выкананае іх аднаго за другім; для медленных API ўсё можна выкананае адночасова.

    Калі гэта будзе працаваць, варта знаты два удосконаленні. Першае — пераконтроўка імені ў цыкле являе сабой спосаб прызначэння задачі адной з канальных працоўных супэрасетак; словнік, які супарабатоўвае імены працоўных супэрасетак з ўсаблікамі гэтых супэрасетак, працюе краща, чым ланцуг if-заяв. Другае — гэта выданне перадае рэзультаты, ствараючы новы текстовы запрос. Болей ідіоматычны падход LangChain — гэта дадаўшы кожны рэзультат як ToolMessage, які несе адпаведны tool_call_id у размову, і зноў запускаючы супэрасетку, прыкрепленую да канальной працоўнай супэрасеткі, што зберагае весь адлічэнне і дазволяе супэрасетцы запрашаць дадатковыя вызывы, якщо першыя рэзультаты недастатковы.

    Расшырэнне асістента вадзіцца паэтапна: канальная працоўная супэрасетка get_financial_news або calculate_valuation падключаецца чераз той самы вызыв bind_tools(), а супэрасетка выбірае працоўную супэрасетку на адной з ўсаблікаў яе апісаў.

    Галоўныя выводы

    • Інструмент — это функцыя з чытальным іменем, падказкамі пра тип і докстрынгам; дэкоратар @tool адмашчва рашты.
    • .bind_tools() паў’язвае вашыя функцыі з модэлем, описуючы іх у кожнай запытце.
    • Модэль просі толькі выканання інструментаў. Ваш код яныя выкананы і вяртае рэзультаты, і гэты контроль ўжоць карысны, а не лімітаванне.
    • Вяртайце выклікі інструментаў як чытальныя строкі, каб адна некоректная запытка не завершала виконання.
    • Пачніце з адного інструмента і адной петлі, а потым, за патрэбай, дадагаўце інструменты, перадачу рэзультатаў па месажах і канкуранцыю.

    Той самы патэрн прыменяецца там, дзе модэлю патрэбны актуальныя даны — ад пагоды і запасоў да записаў CRM чы ўсвойшага базы дадзенаў, такім чынам асистэнты можаць працаваць з жывымі системамі, а не з застойным кадрам.