# Luồng (Flow)

> Một luồng gắn một nguồn dữ liệu đầu vào, một phiên bản mô hình và các nguồn dữ liệu đầu ra. Bật luồng để chạy nó, và chuyển giữa các luồng mà không phải nhập lại cấu hình.

Một **luồng** (flow) là đơn vị bạn chạy. Nó chỉ định một nguồn dữ liệu đầu vào, một phiên bản
mô hình, và không hoặc nhiều nguồn dữ liệu đầu ra. Datasource chỉ mô tả một kết nối, còn mô
hình chỉ mô tả việc cần tính. Luồng ghép chúng lại với nhau, và luồng là thứ bạn bật.

## Vì sao dùng luồng

- **Giữ sẵn các biến thể.** Nhiều luồng có thể dùng chung một nguồn dữ liệu đầu vào. Giữ mỗi
  phiên bản mô hình, hoặc mỗi đích đầu ra, trong một luồng riêng đã cấu hình sẵn.
- **Chuyển trong một bước.** Bật một luồng khác sẽ tắt luồng hiện tại. Bạn không phải nhập
  lại tag, chọn lại mô hình hay map lại đầu ra.
- **Một thứ để vận hành.** Bật, Start, Stop và tắt đều thực hiện trên hàng của luồng.

```mermaid
flowchart LR
  IN["Nguồn dữ liệu đầu vào"] --> A["Luồng A · đang bật\nmodel v2"]
  IN --> B["Luồng B · đang tắt\nmodel v3"]
  A --> O1["Đầu ra: PLC"]
  B --> O2["Đầu ra: MQTT"]
```

## Trước khi bắt đầu

- Một [nguồn dữ liệu đầu vào](/vi/configure/input-datasources/) đã map đủ mọi channel.
- Một [mô hình](/vi/configure/models/) đã tải lên và đã xác thực. Input shape của mô hình phải
  khớp **Window size** và **Tag count** của đầu vào.
- Tùy chọn: một hoặc nhiều [nguồn dữ liệu đầu ra](/vi/configure/output-datasources/). Mỗi đầu
  ra cần **Tag count** bằng số đầu ra của mô hình và ít nhất một channel đã map. Luồng không
  có đầu ra chỉ gửi dự đoán lên dashboard.

## Tạo một luồng

1. ### Mở Quản lý tác vụ

   Đăng nhập bằng tài khoản admin. Trên thanh bên, mở **Quản lý tác vụ** (Task Manager),
   rồi bấm **Luồng mới** (New Flow). Một tên như `Flow_1` được gợi ý; bạn có thể đổi.
   Tên luồng phải là duy nhất.

2. ### Chọn đầu vào

   Chọn nguồn dữ liệu đầu vào mà luồng sẽ đọc.

3. ### Chọn mô hình

   Danh sách chỉ hiện các mô hình khớp với đầu vào đã chọn: input shape của mô hình phải là
   `[window size, tag count]`. Mô hình không hợp lệ hoặc đang xác thực sẽ không được hiển
   thị. Nếu sau đó bạn đổi đầu vào, mô hình không còn khớp sẽ bị bỏ chọn và một thông báo
   cho bạn biết.

4. ### Chọn đầu ra

   Danh sách chỉ hiện các đầu ra có **Tag count** bằng số đầu ra của mô hình. Không chọn
   gì để chỉ giữ dự đoán trên dashboard.

5. ### Lưu

   Bấm **Lưu**. Luồng được lưu ở trạng thái tắt.

## Bật và bắt đầu

Bật công tắc **Bật** (Enabled) trên hàng của luồng. Vì tag mapping và mô hình có thể thay
đổi sau khi lưu, việc bật sẽ kiểm tra lại toàn bộ luồng:

- Input shape của mô hình khớp window size và tag count của đầu vào, và số đầu ra của mô
  hình bằng tag count của từng đầu ra.
- Mọi channel đầu vào đã được map: đúng một tag cho mỗi channel, không tag nào dùng hai lần.
- Mỗi đầu ra đã chọn có ít nhất một channel đã map.

Sau đó nó nạp mô hình và kết nối đầu vào. Cái bắt tay OPC UA hoặc MQTT xảy ra ở đây, nên sự
cố mạng hoặc thông tin xác thực sẽ lộ ra ngay. Nếu bước nào thất bại, công tắc trở về tắt và
một thông báo nêu rõ vấn đề.

Khi bật thành công, các đầu ra của luồng trở thành các đầu ra duy nhất đang hoạt động, và
cột **Suy luận** (Inference) hiển thị **Sẵn sàng**. Bật **không** khởi động truyền dữ liệu.
Bấm **Start** trong cột **Suy luận** để bắt đầu. **Stop** tạm dừng truyền và giữ luồng ở
trạng thái bật.

## Mỗi lần một luồng

Tại mọi thời điểm chỉ tối đa một luồng được bật, và nền tảng bắt buộc điều này. Khi bạn bật
một luồng trong lúc một luồng khác đang bật, một hộp thoại nêu tên luồng sẽ bị tắt. Xác nhận
để chuyển.

**Chuyển thất bại thì không có gì chạy**

Kiểm tra shape chạy trước khi có bất kỳ thay đổi nào. Các bước còn lại chạy sau khi luồng
hiện tại đã bị tắt. Nếu khi đó việc kiểm tra channel, nạp mô hình hoặc kết nối thất bại, sẽ
không có luồng nào được bật. Hãy sửa vấn đề rồi bật lại luồng mới, hoặc bật lại luồng trước.

## Sửa, tắt, xoá

- Chỉ **sửa** một luồng khi nó đang tắt. Sửa luồng đang bật sẽ bị từ chối với thông báo
  *"Disable the flow that uses this before changing it."*
- **Tắt** sẽ dừng truyền, ngắt kết nối đầu vào, gỡ mô hình và dừng các đầu ra của luồng.
  Luồng vẫn giữ cấu hình.
- **Xoá** chỉ xoá luồng. Datasource và mô hình vẫn giữ nguyên. Xoá luồng đang bật sẽ dừng
  pipeline của nó trước.

Không thể xoá một nguồn dữ liệu đầu vào đang được bất kỳ luồng nào sử dụng. Hãy xoá các luồng
đó trước.

## Khi nào luồng tự tắt

Một số chỉnh sửa datasource làm mất hiệu lực những gì luồng đang chạy đã nạp. Khi đó nền
tảng dừng suy luận và tắt luồng, để nó không bao giờ chạy với thiết lập cũ:

- Lưu một thay đổi kết nối trên nguồn dữ liệu đầu vào mà luồng đang bật sử dụng.
- Thay đổi **Tag count**, **Window size** hoặc **Sampling period** của đầu vào. Mọi luồng
  đang bật trên đầu vào đó sẽ bị tắt.
- Lưu tag mapping của đầu vào trong lúc luồng đang dùng nó.

Kiểm tra thay đổi, rồi bật lại luồng và bấm **Start**.

Nếu đầu vào gặp lỗi khi đang truyền (ví dụ một tag ngừng phản hồi), suy luận dừng và mô hình
bị gỡ, nhưng luồng vẫn hiển thị là đang bật. Sửa nguồn, rồi tắt và bật lại luồng để nạp lại,
và bấm **Start**. Xem [Datasource sập hoặc lỗi](/vi/troubleshooting/datasource-down-or-faulted/).

## Tiếp theo

  - [Triển khai một mô hình](/vi/configure/models/) — Tải lên và xác thực mô hình mà luồng sẽ chạy.
  - [Lần suy luận đầu tiên của bạn](/vi/install-deploy/first-inference/) — Bật một luồng, bấm Start và xem dự đoán xuất hiện.
  - [Giám sát runtime](/vi/operate/monitoring/) — Độ trễ, thông lượng (throughput), và KPI.
