3 điểm bởi GN⁺ 2025-05-28 | 1 bình luận | Chia sẻ qua WhatsApp
  • LLM 0.26 là một bản phát hành lớn, cho phép kết nối các công cụ được tạo bằng hàm Python với các mô hình cục bộ OpenAI, Anthropic, Gemini và Ollama trong CLI cũng như thư viện Python
  • Công cụ có thể được cài đặt dưới dạng plugin rồi gọi bằng --tool/-T name_of_tool, hoặc có thể truyền trực tiếp hàm Python tạm thời từ dòng lệnh bằng --functions
  • Ngoài các công cụ tích hợp sẵn llm_version, llm_time, còn có các plugin simpleeval, QuickJS, SQLite, Datasette; mô hình có thể thử lại bằng cách truy vấn schema hoặc dùng biểu thức khác sau một lần gọi thất bại
  • model.chain() mới trong Python API phát hiện yêu cầu gọi công cụ, thực thi rồi truyền kết quả lại cho mô hình, đồng thời hỗ trợ cả hàm đồng bộ và công cụ asyncio
  • Việc triển khai trở nên khả thi khi cách dùng công cụ/gọi hàm của nhiều nhà cung cấp đang hội tụ; các bước tiếp theo là mở rộng plugin, hỗ trợ thêm nhiều plugin mô hình và hỗ trợ client Model Context Protocol

Hỗ trợ chạy công cụ trong LLM 0.26

  • LLM 0.26 bổ sung hỗ trợ công cụ, tính năng lớn nhất kể từ khi dự án bắt đầu
  • Trong LLM CLIthư viện Python, bạn có thể cấp cho các mô hình cục bộ OpenAI, Anthropic, Gemini và Ollama quyền truy cập vào các công cụ có thể biểu diễn bằng hàm Python
  • Khi cài đặt plugin công cụ mới, bạn có thể gắn thêm chức năng mới vào mô hình đang sử dụng
  • Có bốn cách sử dụng chính
    • Cài đặt công cụ dạng plugin và tải bằng --tool/-T name_of_tool
    • Truyền trực tiếp mã hàm Python vào dòng lệnh bằng tùy chọn --functions
    • Trong Python API cũng có thể truyền công cụ theo kiểu tools=[locals]
    • Công cụ hoạt động trong cả ngữ cảnh bất đồng bộ và đồng bộ

Chạy công cụ trong CLI

  • Có thể cài đặt LLM mới nhất bằng uv tool install llm, và nâng cấp bản đã cài bằng uv tool upgrade llm
  • Ví dụ dùng OpenAI: đặt API key bằng llm keys set openai, rồi chạy như sau
llm --tool llm_version "What version?" --td
  • llm_version là công cụ demo đơn giản đi kèm LLM, và --tool llm_version sẽ phơi bày công cụ đó cho mô hình
  • Có thể chỉ định --tool nhiều lần, và cũng có thể dùng tùy chọn ngắn -T
  • --td là viết tắt của --tools-debug, in ra thông tin về lời gọi công cụ và phản hồi để bạn kiểm tra hoạt động bên trong
  • Mô hình mặc định thường là gpt-4o-mini; trong ví dụ, mô hình mặc định được đổi thành gpt-4.1-mini bằng llm models default gpt-4.1-mini
  • Có thể chỉ định mô hình khác bằng tùy chọn -m; cũng có ví dụ chạy o4-mini cùng công cụ tích hợp llm_time
llm --tool llm_time "What time is it?" --td -m o4-mini
  • Phản hồi của công cụ llm_time bao gồm các trường như utc_time, utc_time_iso, local_timezone, local_time, timezone_offset, is_dst

Hoạt động với nhiều mô hình và plugin

  • Có thể dùng cùng mẫu lệnh với các plugin mô hình hỗ trợ công cụ
  • Ví dụ Anthropic Claude Sonnet 4 dùng luồng sau
    • llm install llm-anthropic -U
    • llm keys set anthropic
    • llm --tool llm_version "What version?" --td -m claude-4-sonnet
  • Ví dụ Google Gemini 2.5 Flash dùng luồng sau
    • llm install llm-gemini -U
    • llm keys set gemini
    • llm --tool llm_version "What version?" --td -m gemini-2.5-flash-preview-05-20
  • qwen3:4b chạy bằng Ollama cũng có thể chạy công cụ đơn giản
    • qwen3:4b là một mô hình nhỏ, dung lượng 2,6GB
    • ollama pull qwen3:4b
    • llm install 'llm-ollama>=0.11a0'
    • llm --tool llm_version "What version?" --td -m qwen3:4b

Plugin công cụ cho toán học, JavaScript, SQLite, Datasette

  • Những tác vụ LLM yếu như nhân các số lớn có thể được bổ trợ bằng lời gọi công cụ
  • llm-tools-simpleeval phơi bày thư viện simpleeval của Daniel Fairhead
    • simpleeval là thư viện “Simple Safe Sandboxed Extensible Expression Evaluator for Python”
    • Nó cung cấp một sandbox đủ chắc chắn để chạy các biểu thức Python đơn giản
  • Ví dụ tính toán chạy như sau
llm install llm-tools-simpleeval
llm -T simple_eval 'Calculate 1234 * 4346 / 32414 and square root it' --td
  • Trong lần chạy ví dụ, mô hình trước hết tính 1234 * 4346 / 32414 và nhận 165.45208860368976; sau đó thất bại vì sqrt(...) chưa được định nghĩa, rồi đổi sang ** 0.5 để nhận 12.862818066181678
  • Có bốn plugin công cụ đã được công bố
    • llm-tools-simpleeval: hỗ trợ biểu thức đơn giản như toán học
    • llm-tools-quickjs: cung cấp quyền truy cập vào trình thông dịch JavaScript QuickJS chạy trong sandbox; môi trường được giữ lại giữa các lần gọi nên có thể tái sử dụng biến và hàm
    • llm-tools-sqlite: cung cấp quyền truy cập truy vấn SQL chỉ đọc tới cơ sở dữ liệu SQLite cục bộ
    • llm-tools-datasette: chạy truy vấn SQL trên một instance Datasette từ xa

Hộp công cụ Datasette và thử lại sau lỗi

  • Plugin Datasette hoạt động dưới dạng hộp công cụ có nhiều công cụ bên trong
    • Hộp công cụ là một plugin có thể cấu hình bằng constructor
  • Ví dụ sử dụng như sau
llm install llm-tools-datasette
llm -T 'Datasette("https://datasette.io/content";)' --td "What has the most stars?"
  • Datasette("https://datasette.io/content";) truyền URL instance Datasette sẽ dùng cho plugin
  • Ví dụ này nhắm tới cơ sở dữ liệu content đang vận hành website Datasette
  • Mô hình thực hiện ba lần gọi
    • Ban đầu, nó đoán SELECT name, stars FROM repos ORDER BY stars DESC LIMIT 1 nhưng thất bại vì không có cột stars
    • Sau khi nhận lỗi, nó dùng công cụ Datasette_schema() để truy vấn schema cơ sở dữ liệu
    • Dựa trên schema, nó lắp ghép và chạy truy vấn đúng
  • Theo phản hồi cuối cùng, kho lưu trữ có nhiều sao nhất là datasette, với 10.020 stars

Tạo công cụ tạm thời bằng --functions

  • Tùy chọn --functions cung cấp cách dùng công cụ tạm thời ít cấu trúc hơn so với plugin
  • Nếu truyền trực tiếp một khối mã Python vào dòng lệnh, các hàm được định nghĩa trong đó sẽ trở thành công cụ mà mô hình có thể sử dụng
  • Ví dụ công cụ tìm kiếm blog gọi trang tìm kiếm bằng httpx và trả nguyên HTML về cho mô hình như sau
llm --functions '
import httpx

def search_blog(q):
    "Search Simon Willison blog"
    return httpx.get("https://simonwillison.net/search/";, params={"q": q}).content
' --td 'Three features of sqlite-utils' -s 'use Simon search'
  • Cách triển khai chỉ trả lại nguyên HTML của trang tìm kiếm nhưng vẫn hoạt động
  • Do dòng GPT-4.1 xử lý được 1 triệu token, có thể xử lý cả HTML thô
  • Cần thêm use Simon search vào system prompt để mô hình dùng công cụ tìm kiếm được cung cấp thay vì tự trả lời
  • Một công cụ tìm kiếm tốt hơn cần chỉ dẫn chi tiết hơn và các đoạn trích liên quan từ kết quả tìm kiếm
  • Trong kết quả ví dụ, các tính năng của sqlite-utils gồm kết hợp CLI với thư viện Python, tự động thêm cột thông qua alter=True, và hỗ trợ plugin

Hỗ trợ công cụ trong Python API

  • LLM vừa là công cụ CLI vừa là thư viện Python, và trong 0.26, hỗ trợ công cụ cũng được thêm vào Python API
  • Ví dụ giải bài toán đếm số chữ r trong “strawberry” bằng công cụ dạng hàm
import llm

def count_char_in_text(char: str, text: str) -> int:
    "How many times does char appear in text?"
    return text.count(char)

model = llm.get_model("gpt-4.1-mini")
chain_response = model.chain(
    "Rs in strawberry?",
    tools=[count_char_in_text],
    after_call=print
)
for chunk in chain_response:
    print(chunk, end="", flush=True)
  • after_call=print là cách kiểm tra lời gọi công cụ, tương tự tùy chọn --td ở trên
  • Phương thức mới model.chain() giống model.prompt(), nhưng phát hiện yêu cầu gọi công cụ được trả về, thực thi, rồi gọi lại mô hình cùng kết quả
  • model.chain() có thể chạy nhiều phản hồi trước khi đưa ra câu trả lời cuối cùng
  • Khi lặp qua chain_response, có thể in streaming các token được trả về qua nhiều phản hồi
  • Trong kết quả ví dụ, công cụ count_char_in_text được gọi với char='r', text='strawberry', và dựa trên kết quả 3, nó trả lời rằng strawberry có 3 chữ r
  • Thư viện Python cũng hỗ trợ asyncio, và công cụ có thể là hàm async def
  • Nếu mô hình yêu cầu nhiều công cụ bất đồng bộ cùng lúc, thư viện sẽ chạy chúng đồng thời bằng asyncio.gather()
  • Hộp công cụ cũng được hỗ trợ; truyền tools=[Datasette("https://datasette.io/content";)] vào chain() có hiệu quả giống --tool 'Datasette(...)' trong CLI

Bối cảnh triển khai và mẫu sử dụng công cụ

  • Mẫu sử dụng công cụ là cách đã được theo dõi kể từ khi thấy trong ReAcT paper, công bố lần đầu vào tháng 10/2022
  • Mẫu cơ bản rất đơn giản
    • Cho mô hình biết có những công cụ có thể dùng
    • Mô hình yêu cầu thao tác công cụ bằng cú pháp đặc biệt như JSON, XML hoặc tool_name(arguments), rồi dừng lại
    • Mã sẽ phân tích đầu ra đó và thực thi công cụ được yêu cầu
    • Gửi prompt mới kèm kết quả thực thi tới mô hình
  • Cách này hiện hoạt động với gần như mọi mô hình
  • Nhiều mô hình đã được huấn luyện riêng để dùng công cụ, và cũng có các bảng xếp hạng như Berkeley Function-Calling Leaderboard
  • OpenAI, Anthropic, Google, Mistral và Meta đều đưa tính năng dùng công cụ hoặc gọi hàm vào API của họ
  • Ở phía mô hình cục bộ, Ollama đã bổ sung hỗ trợ công cụ vào năm ngoái, và server llama.cpp cũng có tính năng này
  • LLM trước đó đã phát hành hỗ trợ schema vào tháng 2/2025, xem đây là một bước hướng tới hỗ trợ công cụ
  • Thách thức là thiết kế một lớp trừu tượng hoạt động trên nhiều mô hình; khi cách làm của các nhà cung cấp hiện đã hội tụ rõ rệt, việc triển khai mới trở nên khả thi
  • Workshop Building software on top of Large Language Models tại PyCon US là dịp giúp hoàn tất bản triển khai alpha, và cũng có phần tools trong tutorial

Agent và kế hoạch tiếp theo

  • Dù vẫn có sự dè dặt với thuật ngữ “agents”, trong thế giới LLM khái niệm này đang hội tụ thành tools in a loop, và LLM 0.26 cũng gần với hình thức đó
  • Nếu muốn tạo agent, LLM 0.26 có thể là điểm khởi đầu tốt
  • Công việc tiếp theo được tổng hợp thành 13 issue trong LLM tools v2 milestone
    • Chủ yếu là cải thiện hiển thị log chạy công cụ và những vấn đề nhỏ chưa chặn bản phát hành này
    • Các issue bổ sung nằm dưới nhãn tools
  • Plugin là lĩnh vực có tiềm năng được kỳ vọng nhất
    • Đang trực tiếp sử dụng template cookiecutter llm-plugin-tools
    • Có kế hoạch tạo tutorial liên quan
  • Vẫn còn việc bổ sung hỗ trợ công cụ cho nhiều plugin mô hình hơn
  • Hỗ trợ Model Context Protocol cũng nằm trong kế hoạch
    • MCP đang nhanh chóng nổi lên như một cách tiêu chuẩn để mô hình truy cập công cụ
    • Hai tuần trước, các API nhà cung cấp lớn chưa hỗ trợ trực tiếp, nhưng trong 8 ngày gần đây OpenAI, Anthropic và Mistral đã bổ sung
    • Mục tiêu là để LLM hoạt động như một client MCP, giúp mọi người dễ dùng các server MCP do họ viết làm nguồn công cụ bổ sung cho LLM

1 bình luận

 
GN⁺ 2025-05-28
Ý kiến trên Hacker News
  • Trình kết xuất Markdown dạng streaming viết cho công cụ này cũng đáng xem: https://github.com/day50-dev/Streamdown
    Bối cảnh nằm ở https://github.com/simonw/llm/issues/12, và tôi cũng dùng hằng ngày https://github.com/day50-dev/llmehelp, công cụ tmux được xây trên llm của Simon

    • Còn sót một thứ nữa được xây trên llm: một plugin ZSH dùng zle để biến tiếng Anh thành lệnh shell chỉ bằng một phím bấm: https://github.com/day50-dev/Zummoner
      Hôm nay tôi cũng dùng kiểu như $ git find out if abcdefg is a descendent of hijklmnop, và lệnh for i in $(seq 1 6); do printf "%${i}sh${i}\n\n-----\n" | tr " " "#"; done | pv -bqL 30 trong một bình luận khác vốn ban đầu là đầu vào gần với ngôn ngữ tự nhiên hơn nhiều
      Nhấn ctrl-x x thì buffer được gửi tới OpenRouter và được thay thế bằng cú pháp đúng trong chưa đầy 1 giây
    • Thư viện trông thật sự hay, và sẽ rất tốt nếu có hook để plugin có thể tiếp quản cách hiển thị nội dung của công cụ
      Tôi đã mở issue: https://github.com/simonw/llm/issues/1112
      Tôi có đưa vào vài lựa chọn thiết kế nhưng vẫn chưa thấy hoàn toàn đúng, nên muốn nhận phản hồi
    • Tôi từng tự viết trình kết xuất Markdown dạng streaming bằng nhiều ngôn ngữ để hiển thị nhanh đầu ra LLM dạng streaming, nên rất vui khi thấy không chỉ mình làm vậy
    • Nghe thú vị nên tôi sẽ xem thử; hiện tại tôi đang dùng llm cùng tô sáng cú pháp của bat
  • Cái này làm tăng mạnh nguy cơ tự bắn vào chân
    Tài liệu https://llm.datasette.io/en/stable/tools.html có cảnh báo về prompt injection, nhưng tôi nghĩ kịch bản hợp lý hơn là tự mình gây hại cho mình
    Ví dụ, nếu cấp cho công cụ quyền truy cập tài khoản chứng khoán để tự động hóa giao dịch, thì ngay cả khi không có prompt injection cũng không có cơ chế nào ngăn bot thực hiện các giao dịch ngu ngốc

    • Đúng, rủi ro thật sự tăng lên
      Một khi bắt đầu gắn công cụ vào LLM, đặc biệt nếu các lệnh gọi công cụ đó đã được xác thực và còn có thể thay mặt bạn hành động, thì có quá nhiều con đường để mọi thứ đi sai
      Phía MCP hiện đang trải qua điều này với tốc độ cực nhanh, và vụ GitHub MCP hôm qua cũng là một ví dụ: https://news.ycombinator.com/item?id=44097390
      Tôi đã đưa cảnh báo lớn vào tài liệu, và cũng cẩn trọng chỉ phát hành các plugin công cụ ban đầu không thể gây thiệt hại. Vì vậy sandbox QuickJS và plugin SQLite đều chỉ đọc
    • Nếu ai đó nối llm với tài khoản chứng khoán thì kẻ ngu không phải là bot mà là người đã nối nó
    • Sandboxing sẽ là mấu chốt
      Trên macOS thì không quá khó, nhưng hiện giờ thiếu công cụ tốt, dễ dùng. Claude Code đã bắt đầu dùng Seatbelt từng chút một để cải thiện trải nghiệm người dùng
    • Tôi nghĩ cuộc thảo luận về tự bắn vào chân đang bỏ lỡ điểm chính
      Bạn có thể tự làm hại mình và có lẽ sẽ như vậy, nhưng việc không đánh giá các khả năng cũng là rủi ro. Người bình thường có xu hướng đánh giá thấp khả năng tự bắn vào chân, còn dân kỹ thuật lại có xu hướng đánh giá thấp rủi ro của việc không học các khả năng mới
      Một năm trước tôi cũng đã để LLM chạy lệnh cục bộ trên laptop của mình; tôi xem nó là có rủi ro ở mức nào đó, nhưng chưa có chuyện gì gây hại xảy ra. Với prompt như find out where I am and what weather it is going to be, dù vẫn có khả năng nó chạy rm -rf /, xác suất là rất thấp
      Tuy vậy, giao giao dịch cổ phiếu cho LLM khi không biết nó quyết định thế nào thì theo tiêu chuẩn của tôi là quá rủi ro
    • Bất kỳ công cụ nào cũng có thể bị dùng sai
  • Tôi thích ý tưởng agent chạy trong terminal của Warp Terminal, nhưng không thích mô hình kiểu Cursor: “cứ tin và trả tiền, prompt tốt và các lệnh gọi LLM để chúng tôi lo”
    Vì vậy tôi đã tìm một agent terminal đơn giản dựa trên CLI để bù cho kỹ năng shell còn yếu, và kết hợp công cụ terminal với llm trông là một giải pháp nhẹ nhàng
    Tôi hiểu rõ nguy cơ tự bắn vào chân là lớn, nên tò mò liệu có thể áp dụng cách hỏi quyền cho từng lệnh gọi công cụ như các agent khác không. Ví dụ kiểu “llm sắp gọi rm -rf ./*. Nhấn Y để xác nhận” thì có thể phần nào ngăn LLM chạy loạn trong terminal

    • Tôi từng thắc mắc vì sao terminal đó quảng cáo khắp nơi và tài trợ nhiều dự án, giờ mới biết là nó không hoàn toàn miễn phí
    • Tôi nghĩ đó chẳng phải là cách codex CLI hoạt động mặc định khi không truyền --full-auto sao
  • Nếu đang dùng llm, Gtk-llm-chat cũng đáng xem
    Nó tích hợp với công cụ dòng lệnh llm và desktop, cung cấp biểu tượng khay hệ thống cùng cửa sổ chat đẹp mắt
    Gần đây đã phát hành 3.0.0 và cung cấp gói cho 3 hệ điều hành desktop lớn

    • Ngoài chat thông thường thì tò mò mọi người dùng nó vào việc gì
  • Tôi xem bản phát hành này là một thành phần cốt lõi để mở khóa tiềm năng của LLM mà không bị giới hạn bởi các client hiện có
    Sau khi 0.26 alpha ra mắt, tôi đã thử tạo plugin tương tác với MCP server nhưng khá khó. Đến giờ tôi đã kết nối được và lấy/ dùng động các công cụ, nhưng vẫn chưa truyền được tham số

    • Sáng nay tôi thử xem liệu có thể tạo demo plugin nhanh với MCP không, và thấy khá rắc rối
      Thư viện Python mcp chính thức giả định khá chặt luồng chạy asyncio, kết nối đến server rồi kiểm tra các công cụ khả dụng
  • Tôi đang duy trì một plugin zsh/omz để hỗ trợ tự động hoàn thành bằng phím Tab cho CLI llm gần như hoàn toàn bằng vibe coding, nhưng tốc độ phát hành tính năng mới nhanh quá nên khó theo kịp
    Dù vậy, chỉ cần cỡ llm -f README.md -f llm.plugin.zsh -f completions/_llm -f [https://simonwillison.net/2025/May/27/llm-tools/](<https://simonwillison.net/2025/May/27/llm-tools/>;) "implement tab completions for the new tool plugins feature" là giải quyết được khoảng 90%
    Kho lưu trữ là https://github.com/eliyastein/llm-zsh-plugin, và vì tôi cố nhét càng nhiều tùy chọn và flag càng tốt nên hơi lộn xộn, rất muốn nhận phản hồi

    • Điều hơi đáng kinh ngạc là đây không phải khoa học viễn tưởng, mà chỉ là cách lập trình hiện nay
      Các thế hệ tương lai sẽ thắc mắc chúng ta đã làm việc bằng cách nào, giống như cách chúng ta nhìn các lập trình viên assembly và nghĩ “họ đã làm việc kiểu gì vậy?”
  • Tôi từng thắc mắc Claude Code biết và sử dụng công cụ như thế nào
    Có thể cho LLM biết về công cụ và cách dùng, và wrapper thực thi có thể quản lý việc đó, nhưng tôi nghĩ Claude Code có những kỳ vọng rất cụ thể về API gọi công cụ mà wrapper dùng, và có lẽ đã được củng cố mạnh bằng hậu huấn luyện hoặc tinh chỉnh
    Vì vậy tôi tự hỏi liệu các framework gọi công cụ của bên thứ ba dùng Claude có bất lợi hơn framework của chính Anthropic hay không
    Riêng một vấn đề khác, như bài viết về “tấn công” GitHub MCP đã nói, LLM có thể bị lừa dùng toàn bộ quyền của thông tin xác thực. Vì GitHub có thông tin xác thực phân quyền chi tiết, và công ty chúng tôi cũng vậy, tôi mong ai đó thử một giao thức để wrapper tạo thông tin xác thực được phân quyền chi tiết rồi chuyển cho LLM
    Tôi hình dung một cấu trúc trong đó ứng dụng được cấp thông tin xác thực mạnh hơn, còn LLM cấp dưới được huấn luyện để “yêu cầu quyền” cho một tác vụ hoặc tài nguyên cụ thể. Nếu người dùng cho phép, framework sẽ nhận thông tin xác thực có phạm vi giới hạn từ dịch vụ và dùng nó cho lệnh gọi công cụ

    • Cách dùng thông tin xác thực đó hiện cũng có thể thực hiện bằng hỗ trợ công cụ của LLM
      Cần một cấu hình công cụ khá tinh vi: công khai một công cụ “yêu cầu thông tin xác thực bổ sung”, và khi công cụ đó được gọi thì hỏi người dùng
      Công cụ phải lưu giữ thông tin xác thực và tuyệt đối không chuyển token thật cho LLM; thay vào đó có thể chuyển một ký hiệu như creds1 và bảo LLM dùng creds1 cho các yêu cầu sau
  • Tôi tò mò không biết bạn đã xem bài báo này chưa. Nếu nó quan trọng như vẻ ngoài, tôi nghĩ chỉ số này đáng lẽ phải có trong mọi system card
    Khi đánh giá 12 LLM phổ biến tuyên bố hỗ trợ ngữ cảnh từ 128K token trở lên, chúng hoạt động tốt ở ngữ cảnh ngắn nhưng hiệu năng giảm mạnh khi độ dài ngữ cảnh tăng. Ở mức 32K, 10 mô hình tụt xuống dưới 50% so với đường cơ sở độ dài ngắn; ngay cả GPT-4o, một ngoại lệ có hiệu năng tốt, cũng giảm từ 99,3% xuống 69,7%
    https://arxiv.org/abs/2502.05167

    • Tôi chưa xem bài báo này, nhưng thật sự rất thú vị
      Tôi được biết trong các needle in a haystack test gần đây, Gemini 2.5 Pro và Gemini 2.5 Flash vượt xa các mô hình khác, nên sẽ rất hay nếu chạy thử cả trên các mô hình đó
  • Tuần trước tôi đã làm một bản demo chatbot cho khách hàng dựa trên dữ liệu độc quyền bằng 0.26a0
    Các thành phần cốt lõi tôi phải tự viết là system prompt, công cụ lấy dữ liệu bên ngoài và công cụ thực hiện tính toán; nhờ thư viện này, phần chức năng cốt lõi có thể được xây dựng rất dễ dàng
    Trong demo, phần lớn công sức nằm ở việc làm hạ tầng kết nối: giữ được cuộc hội thoại, làm mới tự nhiên ngay cả khi trình duyệt được refresh do vấn đề kết nối, và tạo một UI web đẹp mắt để có thể bắt đầu phiên chat mới
    Tôi không biết after_call=print, nên đọc bài blog mới biết và thấy rất hay

  • Tôi dùng các công cụ của Simon hằng ngày
    Nhờ pipe và khả năng chuyển đổi dễ dàng giữa Ollama cục bộ với mô hình từ xa, làm việc rất tiện