Strona główna / Artykuły / Uwagi praktyczne: Lokalny agent wsparcia z SmolLM3: tryb myślenia, narzędzia i

Uwagi praktyczne: Lokalny agent wsparcia z SmolLM3: tryb myślenia, narzędzia i

Praktyczne wskazówki: Agent wsparcia lokalnego z SmolLM3 – tryb myślenia, narzędzia oraz umowy, sprawdzenia i pola na kod dla zespołów wdrażających ten wzorzec.

1641 słów

Niech to służy jako wersja przeznaczona dla operatorów, zawierająca idee z „A Local Support Agent with SmolLM3: Think Mode, Tools, and When Not to Reason”: wyraźne etapy, uporządkowane sekcje kodu oraz notatki dotyczące przywracania stanu po przeniesieniu zadania. Etap Przeglądu działa najlepiej, gdy traktowany jest jako mierzalna powierzchnia do analizy. Zapisz jeden idealny zapis rozmowy, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia zmian, zanim rozszerzysz zakres pracy. Traktuj ten etap jako umowę pomiędzy danymi wejściowymi a zweryfikowanymi wynikami. Nadaj nazwy poszczególnym elementom, zdefiniuj kryteria sukcesu i odrzucaj ciche, częściowe ukończenie zadań.

Ustawienia

Na etapie przygotowań należy zdefiniować dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed zmianą kodu. Operatorzy powinni móc ponownie uruchomić dany krok na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Należy rejestrować czasy wykonywania oraz koszt tokenów lub zapytań obok wyników funkcjonalnych. Wczesna widoczność kosztów zapobiega nieoczekiwanym rachunkom, gdy proces przechodzi z środowiska demonstracyjnego do współdzielonych środowisk. W przypadku, gdy następnym krokiem jest kod lub wywołanie narzędzia, lepiej używać ustrukturyzowanych wyników z walidacją schematu niż tekstu w formie swobodnej.

Wybór między Think a no_think to decyzja produktowa

Aby etap „Myślenie vs Brak myślenia” był skuteczny, należy zdefiniować dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed modyfikacją kodu. Operatorzy powinni móc ponownie uruchomić dany krok na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Konfigurację należy przechowywać poza kodem aplikacji. Pliki środowiskowe, magazyny tajnych danych oraz flagi funkcjonalne powinny znajdować się w jednym miejscu, które operatorzy mogą sprawdzić bez konieczności czytania całej struktury. W przypadku, gdy następnym krokiem jest kod lub wywołanie narzędzia, lepiej używać ustrukturyzowanych wyników z walidacją schematu niż tekstu w formie swobodnej.

messages = [
    {"role": "system", "content": "/no_think"},
    {"role": "user", "content": prompt},
]
tokenizer.apply_chat_template(
    messages,
    tokenize=False,
    add_generation_prompt=True,
    enable_thinking=False,  # the /no_think flag in the system prompt wins if both are set
)
<|im_start|>assistant
<think>

</think>
final = re.sub(r"<think>.*?</think>", "", raw, flags=re.DOTALL).strip()
<tool_call>
{"name": <function-name>, "arguments": <args-json-object>}
</tool_call>
TOOLS = [
    {
        "name": "lookup_order_status",
        "description": (
            "Look up the current status, estimated delivery date, and carrier "
            "for a specific customer order. Call this when the customer mentions "
            "an order number or asks where their order is."
        ),
        "parameters": {
            "type": "object",
            "properties": {
                "order_id": {
                    "type": "string",
                    "description": "The order ID, usually in the format ORD-XXXXXX.",
                }
            },
            "required": ["order_id"],
        },
    }
]
ORDERS = {
    "ORD-4821": {"status": "shipped", "eta": "June 18, 2026", "carrier": "DHL"},
    "ORD-3307": {"status": "processing", "eta": "June 20, 2026", "carrier": None},
    "ORD-1190": {"status": "delivered", "eta": None, "carrier": "FedEx"},
}
def respond_with_tools(user_message: str) -> str:
    messages = [{"role": "user", "content": user_message}]
    turn1 = generate_reply(messages)
    name, args = parse_tool_call(turn1)
    if name == "lookup_order_status":
        result = lookup_order_status(**args)
        messages += [
            {"role": "assistant", "content": turn1},
            {"role": "tool", "content": json.dumps(result), "name": name},
        ]
        return generate_reply(messages)
    return turn1
<tool_call>
{"name": "lookup_order_status", "arguments": {"order_id": "ORD-4821"}}
</tool_call>

To właśnie w przypadku e-maili z zgłoszeniami umiera naiwny model pętli

Dla etapu „E-mail ticket” należy zdefiniować dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed zmianą kodu. Operatorzy powinni móc ponownie wykonać ten krok na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Należy udokumentować zarówno prawidłowy przebieg procesu, jak i ścieżkę naprawczą. Próby ponownych działań, kontrolne punkty ludzkie oraz obsługa wiadomości nieodebranych stanowią część produktu, a nie elementy dodawane później. W przypadku, gdy następnym krokiem jest kod lub wywołanie narzędzia, należy preferować ustrukturyzowane wyniki z walidacją schematu zamiast swobodnie sformułowanego tekstu. Dla etapu „E-mail ticket” należy zdefiniować dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed zmianą kodu. Operatorzy powinni móc ponownie wykonać ten krok na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Traktuj ten etap jako umowę pomiędzy danymi wejściowymi a zweryfikowanymi wynikami. Nazwij poszczególne elementy, zdefiniuj kryteria sukcesu i odrzucaj ciche, częściowe ukończenie zadań.

<tool_call>
{"name": "lookup_order_status", "arguments": {"order_id": "your_order_id"}}
</tool_call>

Ochronniki, które nie są dopracowywane

Gdy zajmujesz się ochronnikami, które nie należą do określonej fazy, najpierw zapisz umowę: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego niepowodzenia. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Obok wyników funkcjonalnych zapisz czas wykonywania oraz koszt tokena lub zapytania. Wczesna widoczność kosztów zapobiega niespodziewanym rachunkom, gdy ścieżka przechodzi z wersji demonstracyjnej do środowisk współdzielonych. Zachowuj w pamięci podręcznej stabilne instrukcje systemu oraz schematy narzędzi. Ponowne wysyłanie identycznego prefiksu jest częstą przyczyną marnotrawstwa zasobów.

ORDER_RE = re.compile(r"^ORD-\d{4,}quot;)
PURE_TOOL_RE = re.compile(r"^\s*<tool_call>(.*?)</tool_call>\s*quot;, re.DOTALL)

def parse_executable_tool_call(output: str):
    cleaned = re.sub(r"<think>.*?</think>", "", output, flags=re.DOTALL).strip()
    match = PURE_TOOL_RE.match(cleaned)
    if not match:
        return None
    payload = json.loads(match.group(1).strip())
    order_id = str(payload.get("arguments", {}).get("order_id", "")).strip()
    if not ORDER_RE.match(order_id):
        return None
    return payload

To, czego to nie dowodzi

Gdy pracujesz nad rozdziałem „Co to nie obejmuje”, najpierw zapisz umowę: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego niepowodzenia. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Przechowuj konfigurację poza kodem aplikacji. Pliki środowiskowe, magazyny tajnych danych oraz flagi funkcjonalne powinny znajdować się w jednym miejscu, które operatorzy mogą sprawdzić bez konieczności czytania całej struktury. Zachowuj w pamięci podręcznej stabilne instrukcje systemowe oraz schematy narzędzi. Ponowne wysyłanie identycznego prefiksu jest częstą przyczyną marnotrawstwa zasobów.

Zrób to

Gdy przechodzisz przez etap „Uruchom to”, najpierw zapisz umowę: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego niepowodzenia. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Zdokumentuj zarówno prawidłowy przebieg działania, jak i ścieżkę naprawczą. Próby ponowne, kontrola przez ludzi oraz obsługa wiadomości błędnych stanowią część produktu, a nie elementy dodawane później. Zachowuj w pamięci podręcznej stabilne instrukcje systemu oraz schematy narzędzi. Ponowne wysyłanie identycznego prefiksu to częsty powód marnotrawstwa zasobów. Gdy przechodzisz przez etap „Uruchom to”, najpierw zapisz umowę: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego niepowodzenia. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Traktuj ten etap jako umowę pomiędzy danymi wejściowymi a zweryfikowanymi wynikami. Nadaj nazwy poszczególnym elementom, zdefiniuj kryteria sukcesu i odrzucaj ciche, częściowe ukończenie zadania.

python llm-learning/smollm3-local-support-agent/code/think_vs_nothink.py
python llm-learning/smollm3-local-support-agent/code/support_agent.py
python llm-learning/smollm3-local-support-agent/code/support_agent_guarded.py

Lista kontrolna operacyjna

Gdy przechodzisz przez etap listy kontrolnej operacyjnej, najpierw zapisz umowę: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego awarii. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie.

Wolno preferować małe, testowalne jednostki zamiast rozbudowanych skryptów. Gdy jakiś krok zawiedzie, awaria powinna wskazywać na konkretną odpowiedzialność, a nie na skomplikowany łańcuch operacji.

Zachowuj w pamięci tymczasowej stabilne instrukcje systemu oraz schematy narzędzi. Ponowne wysyłanie identycznego prefiksu to częsty powód marnotrawstwa zasobów.

Ujawniaj narzędzia o wąskich schematach oraz z wyraźnymi oznaczeniami efektów ubocznych. Hostowie muszą wiedzieć, które wywołania zmieniają stan systemu, zanim je automatycznie zatwierdzą.

Zastosuj ludzką aprobatę w przypadkach, gdy dochodzi do wydawania pieniędzy lub zmiany danych produkcyjnych. Połączenia skompilowane w czasie kompilacji nie równają się pełnej kompletności biznesowej.

Napisz krótki podręcznik obsługi: jak rotować klucze, jak opróżnić kolejkę z zadań, jak cofnąć ostatnie operacje importu.

Zanim zaczniesz promować tę architekturę, zamroź wersje, utwórz dokładny zapis dla kluczowych ścieżek działania i potwierdź kroki odwracające zmiany. Środowiska współdzielone wymagają ograniczeń szybkości, weryfikacji użytkowników oraz wyraźnego właściciela odpowiedzialnego za rotację haseł. Wolimy nudną niezawodność od sprytnych, jednorazowych demonstracji.

Uwaga dotycząca zeskanowania 0e44ad944ff5: trzymaj klucze dostawcy poza repozytorium, ustaw ograniczenie liczby tokenów na sesję i przechowuj zapisy obok narzędzi do testowania, aby późniejsze zmiany modeli pozostały porównywalne.

Pracując nad notatką dotyczącą wzmocnienia bezpieczeństwa na etapie 0, najpierw zapisz warunki działania: wymagane dane wejściowe, sygnał sukcesu oraz to, co się dzieje przy częściowym niepowodzeniu. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Udokumentuj zarówno prawidłowy przebieg działania, jak i ścieżkę odzyskiwania. Próby ponowne, kontrola przez ludzi oraz obsługa wiadomości błędnych stanowią część produktu, a nie elementy dodawane później.

Szczegół wzmocnienia 0/868: zmierz czas wykonywania, klasę błędu oraz zużycie tokenów dla tej notatki, a następnie zdecyduj, czy zachować zmianę na podstawie ustalonego zestawu pytań, a nie jedynie anegdoty.

Faza 1 notatki o wzmocnieniu działa najlepiej, gdy jest traktowana jako mierzalna powierzchnia do analizy. Zapisz jeden idealny przepis działania, jeden przypadek awarii oraz notatkę o cofnięciu zmiany przed rozszerzeniem zakresu. Traktuj tę fazę jako umowę pomiędzy danymi wejściowymi a zweryfikowanymi wynikami. Nadaj nazwy poszczególnym elementom, zdefiniuj kryteria sukcesu i odrzuć ciche, częściowe ukończenie zadania.

Szczegół wzmocnienia 1/868: zmierz czas wykonywania, klasę błędu oraz zużycie tokenów dla tej notatki, a następnie zdecyduj, czy zachować zmianę na podstawie ustalonego zestawu pytań, a nie jedynie anegdoty.

Dla drugiego etapu ulepszeń związanych z zabezpieczeniami należy określić dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed modyfikacją kodu. Operatorzy powinni móc ponownie wykonać ten krok na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Konfigurację należy przechowywać poza kodem aplikacji. Pliki środowiskowe, magazyny tajnych danych oraz flagi funkcjonalne powinny znajdować się w jednym miejscu, które operatorzy mogą sprawdzić, nie musząc czytać całej struktury aplikacji.

Szczegóły ulepszenia nr 2/868: należy zmierzyć czas wykonywania, klasę błędów oraz zużycie tokenów dla tego etapu, a następnie podjąć decyzję o zachowaniu zmiany na podstawie ustalonego zestawu kryteriów, a nie opisów przypadkowych.

Gdy przechodzisz przez trzeci etap notatki dotyczącej wzmocnienia bezpieczeństwa, najpierw zapisz warunki realizacji: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego niepowodzenia. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Wolno preferować małe, testowalne jednostki zamiast rozbudowanych skryptów. Gdy jakiś krok się nie powiedzie, błąd powinien wskazywać na konkretną odpowiedzialność, a nie na skomplikowany proces.

Szczegół 3/868 dotyczący wzmocnienia bezpieczeństwa: zmierz czas wykonywania, klasę błędu oraz zużycie tokenów dla tej notatki, a następnie zdecyduj, czy zachować zmianę na podstawie ustalonego zestawu pytań, a nie opisów z praktyki.

Literatura pokrewna

  • 74ce6b13862c dla systemów produkcyjnych — umowy i sprawdzenia — Praktyczny przewodnik po 74ce6b13862c dla systemów produkcyjnych — umowy i sprawdzenia: umowy, sprawdzenia oraz miejsca na kod do wstawienia dla zespołów wdrażających ten wzorzec.
  • Sortowanie ticketów za pomocą Jev, stosowanie jego reguł w Pythonie i wykorzystanie LLM — Praktyczny przewodnik po sortowaniu ticketów za pomocą Jev, stosowaniu jego reguł w Pythonie i wykorzystaniu LLM: umowy, sprawdzenia oraz miejsca na kod do wstawienia dla zespołów wdrażających ten wzorzec.