Anthropic Claude může nyní používat nástroje: RAG chatbot pro zákaznické služby

V tomto návodu vám ukážu jednu kuchařku na připojení nástroje Retriever pro model Claude Opus od Anthropic. Aktuálně nejlepší a nejvýkonnější model LLM. Konkrétně si ukážeme, jak vytvořit chatbot pro zákaznickou podporu.

Další návody najdete na stránce dokumentace Anthropic.

Proč tato metoda?

  • Model Claude má podle posledních hodnocení nejlepší výsledky a předběhl i GPT-4.
  • Jedna z funkcí, která modelu ještě donedávna chyběla, byl právě RAG.
  • RAG je způsob, jak dát modelu k dispozici aktuální a přesné informace.
  • V tomto příkladu si ukážeme jednouchou simulaci, nebudeme přistupovat ke konkrétní databázi.

Technologie

  • Model Claude-3 Opus
  • Nástroje: Retriever pro získávání konkrétních informací objednávek a zákazníků

Script

Pojďme rovnou na konkrétní kód.

Nainstalujeme knihovnu Anthropic.

!pip install anthropic

Importujeme Anthropic, nastavíme model a přidáme vlastní API klíč pro autorizaci.

import anthropic

client = anthropic.Client()
MODEL_NAME = "claude-3-opus-20240229"
client = anthropic.Anthropic(
    api_key="Váš api klíč",
)

Nastavíme nástroje pro získávání informací o zákaznících, objednávkách a možnost zrušení objednávky.

tools = [
    {
        "name": "get_customer_info",
        "description": "Získává informace o zákaznících na základě jejich ID zákazníka. Vrátí jméno, e-mail a telefonní číslo zákazníka.",
        "input_schema": {
            "type": "object",
            "properties": {
                "customer_id": {
                    "type": "string",
                    "description": "Jedinečný identifikátor pro zákazníka."
                }
            },
            "required": ["customer_id"]
        }
    },
    {
        "name": "get_order_details",
        "description": "Načte podrobnosti konkrétní objednávky na základě ID objednávky. Vrátí ID objednávky, název produktu, množství, cenu a stav objednávky.",
        "input_schema": {
            "type": "object",
            "properties": {
                "order_id": {
                    "type": "string",
                    "description": "Jedinečný identifikátor objednávky."
                }
            },
            "required": ["order_id"]
        }
    },
    {
        "name": "cancel_order",
        "description": "Zruší objednávku na základě poskytnutého ID objednávky. Pokud je zrušení úspěšné, vrátí potvrzovací zprávu.",
        "input_schema": {
            "type": "object",
            "properties": {
                "order_id": {
                    "type": "string",
                    "description": "Jedinečný identifikátor objednávky, která má být zrušena."
                }
            },
            "required": ["order_id"]
        }
    }
]

Nastavíme si ukázkové informace, na které se následně budeme dotazovat. Informace o zákaznících, objednávkách, množství, stavu, atd.

def get_customer_info(customer_id):
    # Simulated customer data
    customers = {
        "C1": {"name": "Jan Novák", "email": "jan@example.com", "phone": "123-456-789"},
        "C2": {"name": "Jana Svobodná", "email": "jana@example.com", "phone": "987-654-321"},
        "C3": {"name": "Petr Vlk", "email": "petr@example.com", "phone": "555-666-777"},
        "C4": {"name": "Lucie Králová", "email": "lucie@example.com", "phone": "222-333-444"},
        "C5": {"name": "Tomáš Hruška", "email": "tomas@example.com", "phone": "777-888-999"},
        "C6": {"name": "Eva Pilařová", "email": "eva@example.com", "phone": "111-222-333"},
        "C7": {"name": "Marek Němec", "email": "marek@example.com", "phone": "444-555-666"},
        "C8": {"name": "Anna Šťastná", "email": "anna@example.com", "phone": "999-000-111"},
        "C9": {"name": "David Prachař", "email": "david@example.com", "phone": "888-777-666"},
        "C10": {"name": "Barbora Kočí", "email": "barbora@example.com", "phone": "666-555-444"},
        "C11": {"name": "Radek Horák", "email": "radek@example.com", "phone": "333-444-555"},
        "C12": {"name": "Klára Novotná", "email": "klara@example.com", "phone": "123-789-456"}
    }
    return customers.get(customer_id, "Customer not found")

def get_order_details(order_id):
    # Simulated order data
    orders = {
        "O1": {"id": "O1", "product": "Notebook", "quantity": 2, "price": 30000, "status": "Shipped"},
        "O2": {"id": "O2", "product": "Mobil", "quantity": 1, "price": 7000, "status": "Processing"},
        "O3": {"id": "O3", "product": "Tablet", "quantity": 3, "price": 15000, "status": "Delivered"},
        "O4": {"id": "O4", "product": "E-book reader", "quantity": 4, "price": 4000, "status": "Shipped"},
        "O5": {"id": "O5", "product": "Smartwatch", "quantity": 2, "price": 5000, "status": "Processing"},
        "O6": {"id": "O6", "product": "Camera", "quantity": 1, "price": 25000, "status": "Cancelled"},
        "O7": {"id": "O7", "product": "Headphones", "quantity": 2, "price": 3000, "status": "Delivered"},
        "O8": {"id": "O8", "product": "Portable speaker", "quantity": 3, "price": 2000, "status": "Shipped"},
        "O9": {"id": "O9", "product": "External hard drive", "quantity": 1, "price": 10000, "status": "Processing"},
        "O10": {"id": "O10", "product": "Wireless charger", "quantity": 2, "price": 1500, "status": "Delivered"},
        "O11": {"id": "O11", "product": "USB drive", "quantity": 5, "price": 500, "status": "Shipped"},
        "O12": {"id": "O12", "product": "Gaming mouse", "quantity": 2, "price": 2000, "status": "Cancelled"}
    }
    return orders.get(order_id, "Order not found")

def cancel_order(order_id):
    # Update simulated order cancellation to handle new orders
    valid_orders = ["O1", "O2", "O3", "O4", "O5", "O6", "O7", "O8", "O9", "O10", "O11", "O12"]
    if order_id in valid_orders:
        return True
    else:
        return False

Nastavíme funkci pro volání nástrojů.

def process_tool_call(tool_name, tool_input):
    if tool_name == "get_customer_info":
        return get_customer_info(tool_input["customer_id"])
    elif tool_name == "get_order_details":
        return get_order_details(tool_input["order_id"])
    elif tool_name == "cancel_order":
        return cancel_order(tool_input["order_id"])

Nyní připravíme samotného chatbota a nastavíme parametry modelu a použití nástrojů dle potřeby.

import json

def chatbot_interaction(user_message):
    print(f"\n{'='*50}\nUser Message: {user_message}\n{'='*50}")

    messages = [
        {"role": "user", "content": user_message}
    ]

    response = client.beta.tools.messages.create(
        model=MODEL_NAME,
        max_tokens=4096,
        tools=tools,
        messages=messages
    )

    print(f"\nInitial Response:")
    print(f"Stop Reason: {response.stop_reason}")
    print(f"Content: {response.content}")

    while response.stop_reason == "tool_use":
        tool_use = next(block for block in response.content if block.type == "tool_use")
        tool_name = tool_use.name
        tool_input = tool_use.input

        print(f"\nTool Used: {tool_name}")
        print(f"Tool Input:")
        print(json.dumps(tool_input, indent=2))

        tool_result = process_tool_call(tool_name, tool_input)

        print(f"\nTool Result:")
        print(json.dumps(tool_result, indent=2))

        messages = [
            {"role": "user", "content": user_message},
            {"role": "assistant", "content": response.content},
            {
                "role": "user",
                "content": [
                    {
                        "type": "tool_result",
                        "tool_use_id": tool_use.id,
                        "content": str(tool_result),
                    }
                ],
            },
        ]

        response = client.beta.tools.messages.create(
            model=MODEL_NAME,
            max_tokens=4096,
            tools=tools,
            messages=messages
        )

        print(f"\nResponse:")
        print(f"Stop Reason: {response.stop_reason}")
        print(f"Content: {response.content}")

    final_response = next(
        (block.text for block in response.content if hasattr(block, "text")),
        None,
    )

    print(f"\nFinal Response: {final_response}")

    return final_response

Užití v praxi

Nyní můžeme použít chatbota a položit mu několik dotazů:

chatbot_interaction("Jaký má telefon zákazník C5?")
chatbot_interaction("Jaký je status objednávky O3?")
chatbot_interaction("Jaké je množství u objednávky č. O6?")
chatbot_interaction("Zruš objednávku č. O1")

A následně chatbot odpověděl takto:


==================================================
User Message: Jaký má telefon zákazník C5?
==================================================

Initial Response:
Stop Reason: tool_use
Content: [TextBlock(text='<thinking>\nAbych mohl/a zjistit telefonní číslo zákazníka, je potřeba zavolat funkci get_customer_info. Tato funkce vyžaduje jeden povinný parametr, kterým je customer_id (identifikátor zákazníka). \n\nV tomto dotazu uživatel poskytl customer_id - "C5". Mám tedy všechny potřebné informace k zavolání funkce get_customer_info.\n</thinking>', type='text'), ToolUseBlock(id='toolu_014SHYb4MTv6uRbLqszvp7tz', input={'customer_id': 'C5'}, name='get_customer_info', type='tool_use')]

Tool Used: get_customer_info
Tool Input:
{
  "customer_id": "C5"
}

Tool Result:
{
  "name": "Tom\u00e1\u0161 Hru\u0161ka",
  "email": "tomas@example.com",
  "phone": "777-888-999"
}

Response:
Stop Reason: end_turn
Content: [TextBlock(text='Podle vrácených informací má zákazník s ID C5 telefonní číslo 777-888-999.', type='text')]

Final Response: Podle vrácených informací má zákazník s ID C5 telefonní číslo 777-888-999.

==================================================
User Message: Jaký je status objednávky O3?
==================================================

Initial Response:
Stop Reason: tool_use
Content: [TextBlock(text='<thinking>\nAbych získal status objednávky O3, potřebuji použít funkci get_order_details. Tato funkce vyžaduje parametr order_id, který byl poskytnut v dotazu uživatele jako "O3". Mám všechny potřebné informace pro volání této funkce.\n</thinking>', type='text'), ToolUseBlock(id='toolu_01KKWgN4euKUEEPb6HYxTkpP', input={'order_id': 'O3'}, name='get_order_details', type='tool_use')]

Tool Used: get_order_details
Tool Input:
{
  "order_id": "O3"
}

Tool Result:
{
  "id": "O3",
  "product": "Tablet",
  "quantity": 3,
  "price": 15000,
  "status": "Delivered"
}

Response:
Stop Reason: end_turn
Content: [TextBlock(text='Podle detailů objednávky je status objednávky O3: Doručeno (Delivered).', type='text')]

Final Response: Podle detailů objednávky je status objednávky O3: Doručeno (Delivered).

==================================================
User Message: Jaké je množství u objednávky č. O6?
==================================================

Initial Response:
Stop Reason: tool_use
Content: [TextBlock(text='<thinking>\nAbych mohl/a najít množství objednané v objednávce O6, potřebuji zavolat funkci get_order_details s ID objednávky jako parametrem.\n\nUživatel poskytl ID objednávky "O6" v dotazu, takže mám všechny nezbytné parametry pro volání funkce get_order_details.\n</thinking>', type='text'), ToolUseBlock(id='toolu_01EUzgG8gJ6mha6x7gbdS97q', input={'order_id': 'O6'}, name='get_order_details', type='tool_use')]

Tool Used: get_order_details
Tool Input:
{
  "order_id": "O6"
}

Tool Result:
{
  "id": "O6",
  "product": "Camera",
  "quantity": 1,
  "price": 25000,
  "status": "Cancelled"
}

Response:
Stop Reason: end_turn
Content: [TextBlock(text='Podle detailů objednávky O6 získaných funkcí get_order_details je množství objednané v této objednávce: 1.', type='text')]

Final Response: Podle detailů objednávky O6 získaných funkcí get_order_details je množství objednané v této objednávce: 1.

==================================================
User Message: Zruš objednávku č. O1
==================================================

Initial Response:
Stop Reason: tool_use
Content: [TextBlock(text='<thinking>\nPro zrušení objednávky potřebuji použít funkci cancel_order. Tato funkce vyžaduje jako povinný parametr order_id.\n\nV požadavku uživatel poskytl číslo objednávky "O1", což je ID objednávky, kterou chce zrušit. Můžu tedy s jistotou odvodit tento povinný parametr:\n\norder_id: "O1"\n\nVzhledem k tomu, že mám všechny potřebné parametry, mohu zavolat funkci cancel_order.\n</thinking>', type='text'), ToolUseBlock(id='toolu_01SSf4up2bavYwKYX6qcTDua', input={'order_id': 'O1'}, name='cancel_order', type='tool_use')]

Tool Used: cancel_order
Tool Input:
{
  "order_id": "O1"
}

Tool Result:
true

Response:
Stop Reason: end_turn
Content: [TextBlock(text='Objednávka č. O1 byla úspěšně zrušena.', type='text')]

Final Response: Objednávka č. O1 byla úspěšně zrušena.
Objednávka č. O1 byla úspěšně zrušena.

Informace skutečně odpovídají naší fiktivní jednouché databázi. Jen je potřeba si dát pozor, že se dotazujeme na stejné číslo ID, které je uvedeno v definici. Pokud tak neučiníte, tak vám model napíše, že ID objednávky nenalezl.

Pokud však chceme nějaké obecnější třídění, tak už základní nastavené funkce nestačí.

chatbot_interaction("najdi mi všechny odeslané objednávky")
==================================================
User Message: najdi mi všechny odeslané objednávky
==================================================

Initial Response:
Stop Reason: end_turn
Content: [TextBlock(text='<thinking>\nKe splnění tohoto požadavku bych potřeboval použít jednu z následujících funkcí:\n\nget_customer_info - tato funkce není relevantní, protože požadavek se netýká informací o zákazníkovi, ale o jeho odeslaných objednávkách.\n\nget_order_details - tato funkce vrací detaily o konkrétní objednávce na základě ID objednávky. Požadavek ale není o jedné konkrétní objednávce, nýbrž o všech odeslaných objednávkách. Navíc požadavek neobsahuje ID objednávky, které je povinným parametrem.\n\ncancel_order - tato funkce slouží ke zrušení objednávky, což není relevantní pro tento požadavek na nalezení odeslaných objednávek.\n\nZávěr: Žádná z dostupných funkcí neumožňuje přímo najít všechny odeslané objednávky. Chybí funkce typu "get_all_orders" nebo "search_orders". Navíc v požadavku není specifikováno, pro jakého zákazníka mají být objednávky hledány - chybí ID nebo jiný identifikátor zákazníka.\n</thinking>\n\nOmlouvám se, ale v současné době nemám k dispozici funkci, která by umožňovala najít všechny odeslané objednávky. Pro vyhledání objednávek bych potřeboval znát alespoň ID zákazníka, jehož objednávky mám najít. Pokud mi poskytnete ID zákazníka, rád se pokusím najít detaily jeho jednotlivých objednávek pomocí funkce "get_order_details". Alternativně by bylo potřeba doplnit nějakou funkci pro vyhledávání objednávek podle zadaných kritérií.', type='text')]

Final Response: <thinking>
Ke splnění tohoto požadavku bych potřeboval použít jednu z následujících funkcí:

get_customer_info - tato funkce není relevantní, protože požadavek se netýká informací o zákazníkovi, ale o jeho odeslaných objednávkách.

get_order_details - tato funkce vrací detaily o konkrétní objednávce na základě ID objednávky. Požadavek ale není o jedné konkrétní objednávce, nýbrž o všech odeslaných objednávkách. Navíc požadavek neobsahuje ID objednávky, které je povinným parametrem.

cancel_order - tato funkce slouží ke zrušení objednávky, což není relevantní pro tento požadavek na nalezení odeslaných objednávek.

Závěr: Žádná z dostupných funkcí neumožňuje přímo najít všechny odeslané objednávky. Chybí funkce typu "get_all_orders" nebo "search_orders". Navíc v požadavku není specifikováno, pro jakého zákazníka mají být objednávky hledány - chybí ID nebo jiný identifikátor zákazníka.
</thinking>

Změníme tedy trochu kód a přidáme nástroj na vyhledávání stavu objednávek.

tools = [
    {
        "name": "get_customer_info",
        "description": "Získává informace o zákaznících na základě jejich ID zákazníka. Vrátí jméno, e-mail a telefonní číslo zákazníka.",
        "input_schema": {
            "type": "object",
            "properties": {
                "customer_id": {
                    "type": "string",
                    "description": "Jedinečný identifikátor pro zákazníka."
                }
            },
            "required": ["customer_id"]
        }
    },
    {
        "name": "get_order_details",
        "description": "Načte podrobnosti konkrétní objednávky na základě ID objednávky. Vrátí ID objednávky, název produktu, množství, cenu a stav objednávky.",
        "input_schema": {
            "type": "object",
            "properties": {
                "order_id": {
                    "type": "string",
                    "description": "Jedinečný identifikátor objednávky."
                }
            },
            "required": ["order_id"]
        }
    },
    {
        "name": "cancel_order",
        "description": "Zruší objednávku na základě poskytnutého ID objednávky. Pokud je zrušení úspěšné, vrátí potvrzovací zprávu.",
        "input_schema": {
            "type": "object",
            "properties": {
                "order_id": {
                    "type": "string",
                    "description": "Jedinečný identifikátor objednávky, která má být zrušena."
                }
            },
            "required": ["order_id"]
        }
    },
    {
        "name": "search_orders",
        "description": "Vyhledá všechny objednávky podle zadaného stavu. Vrátí seznam objednávek s jejich detaily.",
        "input_schema": {
            "type": "object",
            "properties": {
                "status": {
                    "type": "string",
                    "description": "Stav objednávky pro vyhledání (např. 'Shipped')."
                }
            },
            "required": ["status"]
        }
    }
]
def search_orders(status):
    # Simulovaná data objednávek
    orders = {
        "O1": {"id": "O1", "product": "Notebook", "quantity": 2, "price": 30000, "status": "Shipped"},
        "O2": {"id": "O2", "product": "Mobil", "quantity": 1, "price": 7000, "status": "Processing"},
        "O3": {"id": "O3", "product": "Tablet", "quantity": 3, "price": 15000, "status": "Delivered"},
        "O4": {"id": "O4", "product": "E-book reader", "quantity": 4, "price": 4000, "status": "Shipped"},
        "O5": {"id": "O5", "product": "Smartwatch", "quantity": 2, "price": 5000, "status": "Processing"},
        "O6": {"id": "O6", "product": "Camera", "quantity": 1, "price": 25000, "status": "Cancelled"},
        "O7": {"id": "O7", "product": "Headphones", "quantity": 2, "price": 3000, "status": "Delivered"},
        "O8": {"id": "O8", "product": "Portable speaker", "quantity": 3, "price": 2000, "status": "Shipped"},
        "O9": {"id": "O9", "product": "External hard drive", "quantity": 1, "price": 10000, "status": "Processing"},
        "O10": {"id": "O10", "product": "Wireless charger", "quantity": 2, "price": 1500, "status": "Delivered"},
        "O11": {"id": "O11", "product": "USB drive", "quantity": 5, "price": 500, "status": "Shipped"},
        "O12": {"id": "O12", "product": "Gaming mouse", "quantity": 2, "price": 2000, "status": "Cancelled"}
    }
    # Vyhledání a vrácení objednávek se zadaným stavem
    matched_orders = {order_id: details for order_id, details in orders.items() if details["status"] == status}
    return matched_orders
def process_tool_call(tool_name, tool_input):
    if tool_name == "get_customer_info":
        return get_customer_info(tool_input["customer_id"])
    elif tool_name == "get_order_details":
        return get_order_details(tool_input["order_id"])
    elif tool_name == "cancel_order":
        return cancel_order(tool_input["order_id"])
    elif tool_name == "search_orders":
        return search_orders(tool_input["status"])

Pokud položíme znovu stejný dotaz, tak je odpověď chatbota již konkrétní a správná.


==================================================
User Message: najdi mi všechny odeslané objednávky
==================================================

Initial Response:
Stop Reason: tool_use
Content: [TextBlock(text='<thinking>\nZ poskytnutých nástrojů se zdá, že pro nalezení všech odeslaných objednávek bude relevantní funkce search_orders. Ta má jeden požadovaný parametr:\n- status: Stav objednávky pro vyhledání\n\nUživatel specifikoval, že chce najít všechny "odeslané" objednávky. To by odpovídalo stavu "Shipped", který zadáme jako hodnotu parametru status.\n</thinking>', type='text'), ToolUseBlock(id='toolu_01PKGW6EzJbQS2qSufJ3J3SF', input={'status': 'Shipped'}, name='search_orders', type='tool_use')]

Tool Used: search_orders
Tool Input:
{
  "status": "Shipped"
}

Tool Result:
{
  "O1": {
    "id": "O1",
    "product": "Notebook",
    "quantity": 2,
    "price": 30000,
    "status": "Shipped"
  },
  "O4": {
    "id": "O4",
    "product": "E-book reader",
    "quantity": 4,
    "price": 4000,
    "status": "Shipped"
  },
  "O8": {
    "id": "O8",
    "product": "Portable speaker",
    "quantity": 3,
    "price": 2000,
    "status": "Shipped"
  },
  "O11": {
    "id": "O11",
    "product": "USB drive",
    "quantity": 5,
    "price": 500,
    "status": "Shipped"
  }
}

Response:
Stop Reason: end_turn
Content: [TextBlock(text='Zde jsou všechny objednávky, které mají stav "Odeslané":\n\n- Objednávka O1: 2x Notebook za 30 000 Kč\n- Objednávka O4: 4x E-book reader za 4 000 Kč\n- Objednávka O8: 3x Přenosný reproduktor za 2 000 Kč \n- Objednávka O11: 5x USB flash disk za 500 Kč\n\nDohromady jsou to 4 odeslané objednávky. Pokud potřebujete nějaké další informace, dejte mi vědět.', type='text')]

Final Response: Zde jsou všechny objednávky, které mají stav "Odeslané":

- Objednávka O1: 2x Notebook za 30 000 Kč
- Objednávka O4: 4x E-book reader za 4 000 Kč
- Objednávka O8: 3x Přenosný reproduktor za 2 000 Kč 
- Objednávka O11: 5x USB flash disk za 500 Kč

Dohromady jsou to 4 odeslané objednávky. Pokud potřebujete nějaké další informace, dejte mi vědět.
Zde jsou všechny objednávky, které mají stav "Odeslané":\n\n- Objednávka O1: 2x Notebook za 30 000 Kč\n- Objednávka O4: 4x E-book reader za 4 000 Kč\n- Objednávka O8: 3x Přenosný reproduktor za 2 000 Kč \n- Objednávka O11: 5x USB flash disk za 500 Kč\n\nDohromady jsou to 4 odeslané objednávky. Pokud potřebujete nějaké další informace, dejte mi vědět.

Můžeme zkusit ještě další typ dotazu:

chatbot_interaction("najdi mi všechny objednávky, které mají vyšší počet kusů než 1")

Odpověď se bohužel nezdařila, protože k tomu nemáme vhodný nástroj.


==================================================
User Message: najdi mi všechny objednávky, které mají vyšší počet kusů než 1
==================================================

Initial Response:
Stop Reason: end_turn
Content: [TextBlock(text="<thinking>\nK vyhledání objednávek podle množství potřebuji použít funkci search_orders. Bohužel tato funkce vyžaduje jako parametr pouze stav objednávky, ne množství. Nemáme k dispozici funkci, která by uměla vyhledat objednávky podle množství objednaných kusů.\n</thinking>\n\nJe mi líto, ale nemám v současné době k dispozici funkci, která by uměla vyhledat objednávky podle počtu kusů v objednávce. Funkce pro vyhledávání objednávek, kterou mám k dispozici, umožňuje pouze vyhledávání podle stavu objednávky (např. 'Odesláno'). \n\nPro vyhledání objednávek s více než 1 kusem by bylo potřeba mít funkci, která přijímá množství jako vstupní parametr. Případně bychom museli projít všechny existující objednávky jednu po druhé pomocí funkce get_order_details a manuálně kontrolovat množství, což by ale bylo velmi neefektivní.\n\nOmlouvám se, že vám nemohu s tímto požadavkem lépe pomoci. Pokud budete mít jakékoliv další dotazy ohledně objednávek nebo zákazníků, rád se na ně pokusím odpovědět pomocí funkcí, které mám aktuálně k dispozici.", type='text')]

Final Response: <thinking>
K vyhledání objednávek podle množství potřebuji použít funkci search_orders. Bohužel tato funkce vyžaduje jako parametr pouze stav objednávky, ne množství. Nemáme k dispozici funkci, která by uměla vyhledat objednávky podle množství objednaných kusů.
</thinking>

Je mi líto, ale nemám v současné době k dispozici funkci, která by uměla vyhledat objednávky podle počtu kusů v objednávce. Funkce pro vyhledávání objednávek, kterou mám k dispozici, umožňuje pouze vyhledávání podle stavu objednávky (např. 'Odesláno'). 

Pro vyhledání objednávek s více než 1 kusem by bylo potřeba mít funkci, která přijímá množství jako vstupní parametr. Případně bychom museli projít všechny existující objednávky jednu po druhé pomocí funkce get_order_details a manuálně kontrolovat množství, což by ale bylo velmi neefektivní.

Omlouvám se, že vám nemohu s tímto požadavkem lépe pomoci. Pokud budete mít jakékoliv další dotazy ohledně objednávek nebo zákazníků, rád se na ně pokusím odpovědět pomocí funkcí, které mám aktuálně k dispozici.
<thinking>\nK vyhledání objednávek podle množství potřebuji použít funkci search_orders. Bohužel tato funkce vyžaduje jako parametr pouze stav objednávky, ne množství. Nemáme k dispozici funkci, která by uměla vyhledat objednávky podle množství objednaných kusů.\n</thinking>\n\nJe mi líto, ale nemám v současné době k dispozici funkci, která by uměla vyhledat objednávky podle počtu kusů v objednávce. Funkce pro vyhledávání objednávek, kterou mám k dispozici, umožňuje pouze vyhledávání podle stavu objednávky (např. 'Odesláno'). \n\nPro vyhledání objednávek s více než 1 kusem by bylo potřeba mít funkci, která přijímá množství jako vstupní parametr. Případně bychom museli projít všechny existující objednávky jednu po druhé pomocí funkce get_order_details a manuálně kontrolovat množství, což by ale bylo velmi neefektivní.\n\nOmlouvám se, že vám nemohu s tímto požadavkem lépe pomoci. Pokud budete mít jakékoliv další dotazy ohledně objednávek nebo zákazníků, rád se na ně pokusím odpovědět pom

Vytvoříme tedy nástroj na vyhledávání objednávek dle kvantity a upravíme původní kód.

tools = [
    {
        "name": "get_customer_info",
        "description": "Získává informace o zákaznících na základě jejich ID zákazníka. Vrátí jméno, e-mail a telefonní číslo zákazníka.",
        "input_schema": {
            "type": "object",
            "properties": {
                "customer_id": {
                    "type": "string",
                    "description": "Jedinečný identifikátor pro zákazníka."
                }
            },
            "required": ["customer_id"]
        }
    },
    {
        "name": "get_order_details",
        "description": "Načte podrobnosti konkrétní objednávky na základě ID objednávky. Vrátí ID objednávky, název produktu, množství, cenu a stav objednávky.",
        "input_schema": {
            "type": "object",
            "properties": {
                "order_id": {
                    "type": "string",
                    "description": "Jedinečný identifikátor objednávky."
                }
            },
            "required": ["order_id"]
        }
    },
    {
        "name": "cancel_order",
        "description": "Zruší objednávku na základě poskytnutého ID objednávky. Pokud je zrušení úspěšné, vrátí potvrzovací zprávu.",
        "input_schema": {
            "type": "object",
            "properties": {
                "order_id": {
                    "type": "string",
                    "description": "Jedinečný identifikátor objednávky, která má být zrušena."
                }
            },
            "required": ["order_id"]
        }
    },
    {
        "name": "search_orders",
        "description": "Vyhledá všechny objednávky podle zadaného stavu. Vrátí seznam objednávek s jejich detaily.",
        "input_schema": {
            "type": "object",
            "properties": {
                "status": {
                    "type": "string",
                    "description": "Stav objednávky pro vyhledání (např. 'Shipped')."
                }
            },
            "required": ["status"]
        }
    },
    {
        "name": "search_orders_by_quantity",
        "description": "Vyhledá všechny objednávky s počtem kusů vyšším než zadaná hodnota.",
        "input_schema": {
            "type": "object",
            "properties": {
                "min_quantity": {
                    "type": "integer",
                    "description": "Minimální počet kusů pro vyhledání objednávek."
                }
            },
            "required": ["min_quantity"]
        }
    }
]

def search_orders_by_quantity(min_quantity):
    # Simulovaná data objednávek
    orders = {
        "O1": {"id": "O1", "product": "Notebook", "quantity": 2, "price": 30000, "status": "Shipped"},
        "O2": {"id": "O2", "product": "Mobil", "quantity": 1, "price": 7000, "status": "Processing"},
        "O3": {"id": "O3", "product": "Tablet", "quantity": 3, "price": 15000, "status": "Delivered"},
        "O4": {"id": "O4", "product": "E-book reader", "quantity": 4, "price": 4000, "status": "Shipped"},
        "O5": {"id": "O5", "product": "Smartwatch", "quantity": 2, "price": 5000, "status": "Processing"},
        "O6": {"id": "O6", "product": "Camera", "quantity": 1, "price": 25000, "status": "Cancelled"},
        "O7": {"id": "O7", "product": "Headphones", "quantity": 2, "price": 3000, "status": "Delivered"},
        "O8": {"id": "O8", "product": "Portable speaker", "quantity": 3, "price": 2000, "status": "Shipped"},
        "O9": {"id": "O9", "product": "External hard drive", "quantity": 1, "price": 10000, "status": "Processing"},
        "O10": {"id": "O10", "product": "Wireless charger", "quantity": 2, "price": 1500, "status": "Delivered"},
        "O11": {"id": "O11", "product": "USB drive", "quantity": 5, "price": 500, "status": "Shipped"},
        "O12": {"id": "O12", "product": "Gaming mouse", "quantity": 2, "price": 2000, "status": "Cancelled"}
    }
    # Filtr objednávek podle množství
    matched_orders = {order_id: details for order_id, details in orders.items() if details["quantity"] > min_quantity}
    return matched_orders

# Případné začlenění do process_tool_call
def process_tool_call(tool_name, tool_input):
    if tool_name == "get_customer_info":
        return get_customer_info(tool_input["customer_id"])
    elif tool_name == "get_order_details":
        return get_order_details(tool_input["order_id"])
    elif tool_name == "cancel_order":
        return cancel_order(tool_input["order_id"])
    elif tool_name == "search_orders":
        return search_orders(tool_input["status"])
    elif tool_name == "search_orders_by_quantity":
        return search_orders_by_quantity(tool_input["min_quantity"])

Výsledkem je správná odpověď na náš původní dotaz.


==================================================
User Message: najdi mi všechny objednávky, které mají vyšší počet kusů než 1
==================================================

Initial Response:
Stop Reason: tool_use
Content: [TextBlock(text='<thinking>\nPro vyhledání objednávek s počtem kusů vyšším než 1 se zdá být nejvhodnější funkce search_orders_by_quantity. Vyžaduje pouze jeden parametr:\n\nmin_quantity - Minimální počet kusů pro vyhledání objednávek. Uživatel v požadavku přímo uvedl, že hledá objednávky s počtem vyšším než 1, takže tento parametr lze nastavit na hodnotu 1.\n\nProtože máme k dispozici všechny potřebné parametry, můžeme funkci zavolat.\n</thinking>', type='text'), ToolUseBlock(id='toolu_013kHhsPhvyyHDu6p7iXMwj5', input={'min_quantity': 1}, name='search_orders_by_quantity', type='tool_use')]

Tool Used: search_orders_by_quantity
Tool Input:
{
  "min_quantity": 1
}

Tool Result:
{
  "O1": {
    "id": "O1",
    "product": "Notebook",
    "quantity": 2,
    "price": 30000,
    "status": "Shipped"
  },
  "O3": {
    "id": "O3",
    "product": "Tablet",
    "quantity": 3,
    "price": 15000,
    "status": "Delivered"
  },
  "O4": {
    "id": "O4",
    "product": "E-book reader",
    "quantity": 4,
    "price": 4000,
    "status": "Shipped"
  },
  "O5": {
    "id": "O5",
    "product": "Smartwatch",
    "quantity": 2,
    "price": 5000,
    "status": "Processing"
  },
  "O7": {
    "id": "O7",
    "product": "Headphones",
    "quantity": 2,
    "price": 3000,
    "status": "Delivered"
  },
  "O8": {
    "id": "O8",
    "product": "Portable speaker",
    "quantity": 3,
    "price": 2000,
    "status": "Shipped"
  },
  "O10": {
    "id": "O10",
    "product": "Wireless charger",
    "quantity": 2,
    "price": 1500,
    "status": "Delivered"
  },
  "O11": {
    "id": "O11",
    "product": "USB drive",
    "quantity": 5,
    "price": 500,
    "status": "Shipped"
  },
  "O12": {
    "id": "O12",
    "product": "Gaming mouse",
    "quantity": 2,
    "price": 2000,
    "status": "Cancelled"
  }
}

Response:
Stop Reason: end_turn
Content: [TextBlock(text='Nalezené objednávky s počtem kusů vyšším než 1 jsou:\n\nO1: 2x Notebook \nO3: 3x Tablet\nO4: 4x E-book reader\nO5: 2x Smartwatch\nO7: 2x Headphones \nO8: 3x Portable speaker\nO10: 2x Wireless charger\nO11: 5x USB drive\nO12: 2x Gaming mouse\n\nCelkem bylo nalezeno 9 objednávek splňujících kritérium minimálního počtu kusů vyššího než 1.', type='text')]

Final Response: Nalezené objednávky s počtem kusů vyšším než 1 jsou:

O1: 2x Notebook 
O3: 3x Tablet
O4: 4x E-book reader
O5: 2x Smartwatch
O7: 2x Headphones 
O8: 3x Portable speaker
O10: 2x Wireless charger
O11: 5x USB drive
O12: 2x Gaming mouse

Celkem bylo nalezeno 9 objednávek splňujících kritérium minimálního počtu kusů vyššího než 1.
Nalezené objednávky s počtem kusů vyšším než 1 jsou:\n\nO1: 2x Notebook \nO3: 3x Tablet\nO4: 4x E-book reader\nO5: 2x Smartwatch\nO7: 2x Headphones \nO8: 3x Portable speaker\nO10: 2x Wireless charger\nO11: 5x USB drive\nO12: 2x Gaming mouse\n\nCelkem bylo nalezeno 9 objednávek splňujících kritérium minimálního počtu kusů vyššího než 1.

Celkově hodnotím spojení Claude-3 a funkce nástrojů jako velmi užitečné pro různé způsoby použití. A velmi se těším na integraci v reálné firemní praxi. Netestoval jsem stejný případ u modelu GPT-4 Turbo, ale z různých nezávislých testů i mého vlastního experimentování zatím plyne, že nový model Claude Opus má lepší uvažování, lépe dodržuje instrukce a jeho odpovědi jsou méně strojově znějící. Pokud opět OpenAI nepřijde brzo s nějakým bombastickým novým modelem, tak je za mě aktuálně králem LLM společnost Anthropic se svými novými modely. Těším se na další nástroje, jako např. search nebo pokročilejší systém RAG pro vlastní data.

Obsah článku

Líbí se Vám obsah?

Odebírejte Newsletter, ať vám nic neunikne.

Odebírejte novinky ze světa AI

Chcete-li se přihlásit k odběru tohoto blogu a dostávat upozornění na nové příspěvky e-mailem, zadejte svou e-mailovou adresu.

Sledujte mě na sítích.

Odběr novinek AI

Odebírejte novinky ze světa AI

Chcete-li se přihlásit k odběru tohoto blogu a dostávat upozornění na nové příspěvky e-mailem, zadejte svou e-mailovou adresu.

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *

Podobné články