Một prompt có đủ để đo source visibility trên ChatGPT? Thử nghiệm 10 prompt × 5 lần chạy
Một prompt có đủ để đo source visibility trên ChatGPT?
Khi đo mức độ xuất hiện của một website hoặc thương hiệu trong các hệ thống AI, có một vấn đề khá dễ bị bỏ qua:
Nếu chạy cùng một prompt hai lần, chúng ta có nhận được cùng một tập nguồn không?
Nếu câu trả lời là không, việc chụp một màn hình rồi kết luận "AI không thấy website này" hoặc "AI đang ưu tiên nguồn kia" có thể khá rủi ro.
Tôi thử kiểm tra vấn đề này bằng một experiment nhỏ:
- 10 prompt cố định
- mỗi prompt chạy 5 lần
- tổng cộng 50 observations
- giữ nguyên câu chữ trong từng nhóm repeat
- so sánh tập domain xuất hiện trong source trace
Mục tiêu của experiment không phải reverse-engineer thuật toán ChatGPT.
Tôi chỉ muốn trả lời một câu thực dụng hơn:
Với một prompt cố định, tập source domain quan sát được ổn định đến mức nào?
1. Trước hết: source trace không phải citation
Đây là distinction quan trọng nhất của experiment.
Trong bài này, tôi gọi source trace là tập URL/domain xuất hiện trong lớp source/search mà tôi quan sát được khi chạy prompt.
Điều đó không đồng nghĩa:
- URL đó chắc chắn được dùng để tạo final answer
- URL được citation trong final answer
- thương hiệu trên URL được mention
- thương hiệu được recommendation
Tôi xem các trạng thái này là những lớp riêng:
search / source discovery
↓
retrieval
↓
citation
↓
mention
↓
recommendation
Một số lớp, đặc biệt retrieval, không phải lúc nào cũng quan sát trực tiếp được.
Vì vậy experiment này chỉ đo:
source-domain set repeatability
chứ không đo độ ổn định của final answer.
2. Dataset
Tôi chọn 10 prompt thuộc ba dạng intent:
- provider selection
- informational / diagnostic
- comparison
Mỗi prompt được chạy 5 lần.
Ví dụ:
P1-R1
P1-R2
P1-R3
P1-R4
P1-R5
là năm lần chạy của cùng prompt P1.
Sau mỗi lần chạy, tôi lấy tập domain duy nhất xuất hiện.
Ví dụ:
R1 = {a.com, b.com, c.com}
R2 = {a.com, b.com, d.com}
Tôi không dùng số lượng URL làm metric chính vì một domain có thể xuất hiện nhiều URL.
Đơn vị so sánh chính là unique domain set.
3. Dùng Jaccard để đo overlap
Để so hai tập domain, tôi dùng Jaccard similarity.
Công thức:
J(A, B) = |A ∩ B| / |A ∪ B|
Ví dụ:
A = {a.com, b.com, c.com}
B = {a.com, b.com, d.com}
Ta có:
intersection = {a.com, b.com} = 2
union = {a.com, b.com, c.com, d.com} = 4
Jaccard = 2 / 4 = 0.5
Nếu hai tập giống hoàn toàn:
J = 1.0
Nếu không có domain nào trùng:
J = 0
Một implementation Python đơn giản:
def jaccard(a, b):
a = set(a)
b = set(b)
if not a and not b:
return 1.0
return len(a & b) / len(a | b)
run_1 = {
"a.com",
"b.com",
"c.com"
}
run_2 = {
"a.com",
"b.com",
"d.com"
}
print(jaccard(run_1, run_2))
# 0.5
Với mỗi prompt tôi tính pairwise Jaccard giữa 5 lần chạy.
5 runs tạo ra:
C(5, 2) = 10
cặp so sánh.
Sau đó lấy mean Jaccard cho từng prompt.
4. Kết quả của 10 prompt
Kết quả tổng hợp:
| Prompt | Số domain R1-R5 | Union sau 5 run | Mean pairwise Jaccard |
|---|---|---|---|
| P01 | 10 / 8 / 8 / 8 / 8 | 10 | 0.920 |
| P02 | 10 / 10 / 10 / 10 / 10 | 10 | 1.000 |
| P03 | 11 / 11 / 10 / 10 / 10 | 11 | 0.909 |
| P04 | 8 / 10 / 10 / 8 / 10 | 10 | 0.880 |
| P05 | 5 / 5 / 5 / 5 / 5 | 6 | 0.867 |
| P06 | 9 / 10 / 10 / 10 / 10 | 10 | 0.960 |
| P07 | 7 / 7 / 7 / 7 / 7 | 7 | 1.000 |
| P08 | 6 / 6 / 6 / 6 / 6 | 6 | 1.000 |
| P09 | 9 / 9 / 9 / 9 / 9 | 9 | 1.000 |
| P10 | 6 / 6 / 6 / 6 / 6 | 6 | 1.000 |
Mean của 10 prompt-level mean Jaccard là khoảng:
0.954
Ngoài ra:
5 / 10 prompt
có exact same domain set trong cả 5 lần chạy.
Điều này cho thấy source set trong sample này khá ổn định.
5. Một lần chạy đã thấy bao nhiêu phần của eventual union?
Thay vì chỉ nhìn Jaccard, tôi thử hỏi:
Sau run đầu tiên, tôi đã quan sát được bao nhiêu phần của toàn bộ domain mà cuối cùng xuất hiện sau 5 run?
Gọi:
U5 = R1 ∪ R2 ∪ R3 ∪ R4 ∪ R5
Coverage sau run đầu:
coverage_1 = |R1| / |U5|
Coverage sau hai run:
coverage_2 = |R1 ∪ R2| / |U5|
Trong sample này:
Run đầu tiên capture trung bình khoảng 95.3% eventual 5-run domain union.
Và đáng chú ý hơn:
Sau hai run, cumulative union đã capture 100% eventual five-run domain union của cả 10 prompt.
Tức là trong experiment này:
R1 ∪ R2
đã chứa toàn bộ domain mà tôi tiếp tục thấy ở R3, R4 và R5.
Repeat 3-5 không mở rộng union domain.
6. Có phải vậy nghĩa là chỉ cần chạy 2 lần?
Không.
Đây chính là nơi experiment rất dễ bị diễn giải quá mức.
Kết quả thực tế chỉ nói rằng:
Trong 10 prompt và cửa sổ collection này, hai source-trace run đầu đã bao phủ eventual 5-run domain union.
Nó không chứng minh rằng:
2 runs = universal optimum
cho mọi audit.
Có một số lý do.
Sample chỉ có 10 prompt
10 prompt đủ để tạo observation ban đầu nhưng quá nhỏ để tạo universal rule.
Các run nằm trong một cửa sổ thời gian ngắn
Nếu chạy lại sau:
1 ngày
1 tuần
1 tháng
search index, retrieval backend hoặc available sources có thể đã thay đổi.
Tôi chỉ đo domain set
Experiment này không đo:
answer wording
citation
brand mention
recommendation
source ordering
Một source set ổn định không có nghĩa final answer cũng ổn định tương đương.
Prompt type có thể ảnh hưởng variance
Provider-selection prompt có thể có behavior khác informational prompt.
Các lĩnh vực freshness-sensitive cũng có thể biến động mạnh hơn.
7. Quy tắc thực dụng mà tôi đang dùng
Sau experiment này, tôi không còn thích cách:
1 prompt
×
1 run
=
1 kết luận
Nhưng tôi cũng chưa thấy cơ sở để luôn chạy 5 hoặc 10 lần cho tất cả prompt.
Với source discovery, rule tôi đang thử dùng là:
Run 1
↓
Run 2
↓
So sánh source set
↓
Nếu tương đối ổn định
→ có thể dừng discovery
Nếu khác đáng kể
→ chạy thêm
Pseudo-code:
runs = []
for i in range(max_runs):
domains = run_prompt()
runs.append(set(domains))
if len(runs) >= 2:
score = jaccard(runs[-1], runs[-2])
if score >= threshold:
# candidate stop condition
# không phải universal rule
pass
Điểm quan trọng là threshold không nên được hard-code chỉ từ experiment này.
Nếu quyết định có tác động lớn, tôi vẫn tăng repeats.
Ví dụ:
- benchmark công khai
- so sánh đối thủ
- báo cáo cho khách hàng
- nghiên cứu longitudinal
đều cần protocol chặt hơn một lần source discovery nhanh.
8. Intersection và union nói hai câu chuyện khác nhau
Giả sử:
R1 = {A, B, C, D}
R2 = {A, B, C, E}
Intersection:
{A, B, C}
có thể xem như core source set.
Union:
{A, B, C, D, E}
lại mô tả source landscape rộng hơn.
Hai metric phục vụ hai mục tiêu khác nhau.
Nếu muốn biết:
Những nguồn nào xuất hiện ổn định?
thì nên quan tâm intersection hoặc frequency.
Nếu muốn biết:
Toàn bộ candidate sources mà model có thể chạm tới là gì?
thì cumulative union hữu ích hơn.
Vì vậy một audit chỉ lưu screenshot của một run sẽ mất khá nhiều thông tin.
9. Nếu làm experiment lại, tôi sẽ thay đổi gì?
Tôi muốn mở rộng một số phần.
Chạy theo nhiều time window
Ví dụ:
T0
T+1 day
T+7 days
T+30 days
để tách:
- within-session variance
- temporal variance
Đo URL-level và domain-level riêng
Hai URL trên cùng domain không hoàn toàn tương đương về evidence.
Tách source role
Ví dụ:
official
provider / first-party
editorial
directory / review
community
research
Có thể domain thay đổi nhưng source role vẫn ổn định.
So final-answer citation riêng
Đây cần một dataset khác.
Không nên lấy source trace để suy ra citation stability.
10. Kết luận
Kết quả đáng chú ý nhất với tôi không phải con số Jaccard 0.954.
Mà là việc một phép đo tưởng khá đơn giản như:
"ChatGPT đang lấy nguồn nào?"
thực tế cần xác định rất rõ:
đơn vị đo là URL hay domain?
source exposure hay citation?
chạy bao nhiêu lần?
cùng thời điểm hay nhiều thời điểm?
intersection hay union?
Trong sample 10 prompt × 5 runs của tôi, source-domain sets ổn định tương đối cao và hai run đầu đã bao phủ eventual five-run domain union.
Nhưng tôi xem đây là một observation để thiết kế protocol tiếp theo, không phải bằng chứng cho một quy tắc cố định của ChatGPT.
Nếu tiếp tục experiment này, bước tôi quan tâm nhất sẽ là:
Source-set stability theo thời gian có còn cao như stability trong cùng một collection window hay không?
All rights reserved