Dynamic Prompt Generation — Tạo prompt tự động theo context và user input
Điểm nổi bật
Nhấn để đến mục tương ứng
- 1 Theo dõi prompt length và tối ưu khi cần — loại bỏ context không cần thiết, rút gọn instructions, giảm số ví dụ mẫu khi user đã quen với hệ thống.
- 2 Dynamic prompt generation là kỹ thuật xây dựng hệ thống tự động tạo prompt phù hợp nhất cho từng tình huống cụ thể, thay vì dùng một prompt duy nhất cho mọi trường hợp.
- 3 Static vs Dynamic Prompts Trước khi đi vào kỹ thuật, hãy hiểu rõ sự khác biệt giữa hai cách tiếp cận.
- 4 Bước tiếp theo Dynamic prompt generation chuyển prompt engineering từ việc viết tay thủ công sang một hệ thống có kiến trúc rõ ràng, testable, và scalable.
- 5 Bắt đầu bằng cách chuyển 2-3 static prompt quan trọng nhất của bạn sang template, thêm context-aware logic, và thiết lập A/B testing cơ bản.
Trong hầu hết ứng dụng AI production, prompt không phải là chuỗi ký tự cố định. Nó cần thay đổi theo ngữ cảnh người dùng, loại tác vụ, dữ liệu đầu vào, và thậm chí cả thời điểm trong ngày. Dynamic prompt generation là kỹ thuật xây dựng hệ thống tự động tạo prompt phù hợp nhất cho từng tình huống cụ thể, thay vì dùng một prompt duy nhất cho mọi trường hợp.
Static vs Dynamic Prompts
Trước khi đi vào kỹ thuật, hãy hiểu rõ sự khác biệt giữa hai cách tiếp cận.
Static prompt
Prompt được viết cố định, dùng cho mọi trường hợp:
SYSTEM_PROMPT = """
Bạn là trợ lý viết nội dung.
Viết bài blog SEO-friendly về chủ đề người dùng yêu cầu.
Độ dài 800-1000 từ, bao gồm tiêu đề H2 và H3.
"""
Vấn đề: Prompt này áp dụng cho mọi chủ đề, mọi đối tượng, mọi giọng điệu. Bài về công nghệ blockchain sẽ có cùng cấu trúc và phong cách với bài về nấu ăn gia đình. Kết quả là nội dung generic, không có cá tính.
Dynamic prompt
Prompt được xây dựng tự động dựa trên ngữ cảnh:
def build_prompt(topic, audience, tone, word_count, seo_keywords):
return f"""
Bạn là chuyên gia viết nội dung trong lĩnh vực {topic.category}.
Viết bài blog về: {topic.title}
Đối tượng đọc: {audience.description}
Giọng điệu: {tone}
Độ dài: {word_count} từ
Từ khóa SEO cần bao gồm: {', '.join(seo_keywords)}
Cấu trúc bài viết:
{generate_structure(topic.complexity)}
Lưu ý đặc biệt cho đối tượng {audience.level}:
{get_audience_guidelines(audience)}
"""
Với cách này, prompt cho bài blockchain sẽ khác hoàn toàn prompt cho bài nấu ăn — về chuyên gia được gán vai, cấu trúc bài, giọng điệu, và hướng dẫn đặc thù.
Template Engine Approach
Cách phổ biến nhất để tạo dynamic prompt là sử dụng template engine. Bạn định nghĩa template với các biến, sau đó điền giá trị vào runtime.
Jinja2-style template
from jinja2 import Template
PROMPT_TEMPLATE = Template("""
Bạn là {{ role }}.
{% if context %}
Ngữ cảnh:
{{ context }}
{% endif %}
Nhiệm vụ: {{ task_description }}
{% if examples %}
Ví dụ mẫu:
{% for example in examples %}
Input: {{ example.input }}
Output: {{ example.output }}
{% endfor %}
{% endif %}
Yêu cầu format:
- Ngôn ngữ: {{ language }}
- Độ dài: {{ word_count }} từ
- Giọng điệu: {{ tone }}
{% if constraints %}
Ràng buộc:
{% for constraint in constraints %}
- {{ constraint }}
{% endfor %}
{% endif %}
""")
# Sử dụng
prompt = PROMPT_TEMPLATE.render(
role="chuyên gia phân tích tài chính",
context="Báo cáo Q4 2024 của công ty ABC",
task_description="Phân tích hiệu suất tài chính và dự báo Q1 2025",
examples=[
{"input": "Doanh thu tăng 15%", "output": "Tín hiệu tích cực..."},
],
language="Tiếng Việt",
word_count=500,
tone="chuyên nghiệp, dựa trên dữ liệu",
constraints=[
"Không đưa ra lời khuyên đầu tư",
"Trích dẫn số liệu cụ thể từ báo cáo",
"So sánh với cùng kỳ năm trước"
]
)
Ưu điểm của template approach
- Tách biệt logic và nội dung: Template là nội dung, code điền giá trị là logic. Dễ thay đổi một bên mà không ảnh hưởng bên kia.
- Tái sử dụng: Cùng template có thể phục vụ nhiều use case khác nhau chỉ bằng cách thay đổi giá trị biến.
- Testable: Có thể viết unit test cho từng template với các bộ giá trị khác nhau.
- Version control: Template là file text, dễ dàng track changes trong Git.
Context-Aware Prompt Construction
Template engine giải quyết vấn đề cấu trúc, nhưng prompt thực sự thông minh cần hiểu ngữ cảnh để tự điều chỉnh. Đây là kỹ thuật context-aware construction.
Thu thập context
Các nguồn context phổ biến trong ứng dụng production:
class PromptContext:
def __init__(self, user, request, session):
# User context
self.user_level = user.expertise_level # beginner/intermediate/expert
self.user_language = user.preferred_lang # vi/en
self.user_history = user.recent_queries # 10 queries gần nhất
# Request context
self.task_type = request.classify_task() # analysis/generation/translation
self.input_length = len(request.content) # Độ dài input
self.input_complexity = request.complexity_score()
# Session context
self.conversation_turn = session.turn_count
self.previous_response = session.last_response
self.accumulated_context = session.context_window_usage
def get_appropriate_detail_level(self):
"""Quyết định mức độ chi tiết phù hợp."""
if self.user_level == "beginner":
return "chi tiết, giải thích từng bước, dùng ví dụ đơn giản"
elif self.user_level == "expert":
return "ngắn gọn, tập trung vào điểm chính, dùng thuật ngữ chuyên môn"
return "cân bằng giữa chi tiết và ngắn gọn"
def get_response_length(self):
"""Tính toán độ dài response phù hợp."""
if self.input_length < 50:
return "200-400 từ"
elif self.input_length < 500:
return "400-800 từ"
return "800-1200 từ"
Xây dựng prompt từ context
class DynamicPromptBuilder:
def __init__(self, template_registry):
self.templates = template_registry
def build(self, context):
"""Xây dựng prompt dựa trên context."""
# Chọn template phù hợp với loại tác vụ
template = self.templates.get(context.task_type)
# Điều chỉnh theo user level
detail_level = context.get_appropriate_detail_level()
response_length = context.get_response_length()
# Thêm conversation history nếu multi-turn
history_section = ""
if context.conversation_turn > 1:
history_section = f"""
Đây là lượt hội thoại thứ {context.conversation_turn}.
Câu trả lời trước đó:
{context.previous_response[:500]}
Hãy tiếp nối ngữ cảnh cuộc hội thoại.
"""
# Điều chỉnh context window
if context.accumulated_context > 0.7:
# Đang dùng hơn 70% context window
# Cần tóm tắt thay vì giữ nguyên
history_section = self._summarize_history(context)
return template.render(
detail_level=detail_level,
response_length=response_length,
history=history_section,
language=context.user_language,
)
User Profiling cho Prompt Customization
Prompt có thể được cá nhân hóa dựa trên hồ sơ người dùng. Đây là cấp độ nâng cao của dynamic prompting, nơi hệ thống "học" cách giao tiếp tốt nhất với từng người dùng.
Xây dựng user profile
class UserProfile:
def __init__(self, user_id):
self.user_id = user_id
self.preferences = self._load_preferences()
def _load_preferences(self):
"""Load preferences từ database hoặc phân tích lịch sử."""
return {
"response_style": "concise", # concise / detailed / balanced
"technical_level": "intermediate",
"preferred_format": "bullet_points", # prose / bullet_points / table
"domain_expertise": ["python", "data-science"],
"language_mix": 0.3, # 0 = thuần Việt, 1 = thuần Anh, 0.3 = chủ yếu Việt kèm thuật ngữ Anh
}
def get_style_instructions(self):
"""Tạo chỉ dẫn phong cách dựa trên preferences."""
instructions = []
if self.preferences["response_style"] == "concise":
instructions.append("Trả lời ngắn gọn, đi thẳng vào vấn đề")
elif self.preferences["response_style"] == "detailed":
instructions.append("Giải thích chi tiết từng bước")
if self.preferences["preferred_format"] == "bullet_points":
instructions.append("Ưu tiên dùng bullet points thay vì đoạn văn dài")
elif self.preferences["preferred_format"] == "table":
instructions.append("Dùng bảng khi so sánh hoặc liệt kê")
if self.preferences["language_mix"] > 0:
instructions.append(
"Có thể dùng thuật ngữ tiếng Anh cho các khái niệm kỹ thuật"
)
return "
".join(f"- {i}" for i in instructions)
Tích hợp vào prompt builder
def build_personalized_prompt(task, user_profile, context):
style = user_profile.get_style_instructions()
expertise = user_profile.preferences["domain_expertise"]
return f"""
Bạn đang hỗ trợ một người dùng có chuyên môn về: {', '.join(expertise)}.
Phong cách giao tiếp:
{style}
Nhiệm vụ: {task.description}
Ngữ cảnh: {context.summary}
{task.specific_instructions}
"""
A/B Testing Prompt Variants trong Production
Khi hệ thống đã chạy, bạn cần cơ chế A/B test để liên tục cải thiện prompt. Đây không phải A/B test thủ công như trong phát triển, mà là hệ thống tự động phân bổ traffic và đo lường kết quả.
Prompt Experiment Framework
import random
import hashlib
class PromptExperiment:
def __init__(self, experiment_id, variants, traffic_split):
self.experiment_id = experiment_id
self.variants = variants # {"control": prompt_a, "variant_1": prompt_b}
self.traffic_split = traffic_split # {"control": 0.5, "variant_1": 0.5}
def assign_variant(self, user_id):
"""Gán variant nhất quán cho mỗi user."""
hash_input = f"{self.experiment_id}:{user_id}"
hash_value = int(hashlib.md5(hash_input.encode()).hexdigest(), 16)
ratio = (hash_value % 1000) / 1000
cumulative = 0
for variant_name, split in self.traffic_split.items():
cumulative += split
if ratio < cumulative:
return variant_name
return list(self.variants.keys())[-1]
def get_prompt(self, user_id):
"""Lấy prompt cho user dựa trên variant assignment."""
variant = self.assign_variant(user_id)
return self.variants[variant], variant
def log_result(self, user_id, variant, metrics):
"""Ghi lại kết quả để phân tích sau."""
record = {
"experiment_id": self.experiment_id,
"user_id": user_id,
"variant": variant,
"metrics": metrics, # {"satisfaction": 4, "task_completed": True}
}
# Lưu vào database hoặc analytics service
save_experiment_result(record)
Metrics để đo lường
Đo lường hiệu quả prompt trong production cần các metric khách quan:
- Task completion rate: Tỷ lệ người dùng hoàn thành tác vụ sau khi nhận response
- Follow-up rate: Tỷ lệ người dùng cần hỏi thêm. Thấp hơn thường tốt hơn.
- User satisfaction: Rating hoặc feedback từ người dùng
- Response quality score: Đánh giá tự động bằng model khác hoặc rubric
- Latency impact: Prompt dài hơn có tăng latency đáng kể không
Prompt Registry Pattern
Trong production, prompt không nên nằm rải rác trong code. Prompt Registry là pattern tập trung quản lý tất cả prompt ở một nơi, giống như config management.
Kiến trúc Prompt Registry
class PromptRegistry:
def __init__(self, storage_backend):
self.storage = storage_backend # Database, file system, hoặc remote config
self.cache = {}
self.experiments = {}
def register(self, prompt_id, template, metadata):
"""Đăng ký prompt mới."""
self.storage.save({
"id": prompt_id,
"template": template,
"version": metadata.get("version", "1.0.0"),
"author": metadata.get("author"),
"created_at": datetime.now().isoformat(),
"tags": metadata.get("tags", []),
"test_results": metadata.get("test_results"),
})
def get(self, prompt_id, context=None, user_id=None):
"""Lấy prompt, có tính đến experiment và context."""
# Kiểm tra xem prompt có đang trong experiment không
if prompt_id in self.experiments:
experiment = self.experiments[prompt_id]
template, variant = experiment.get_prompt(user_id)
else:
template = self._get_template(prompt_id)
variant = "default"
# Render template với context
if context:
return template.render(**context), variant
return template, variant
def rollback(self, prompt_id, target_version):
"""Rollback prompt về phiên bản cũ."""
old_version = self.storage.get_version(prompt_id, target_version)
self.storage.set_active(prompt_id, old_version)
self.cache.pop(prompt_id, None)
def list_prompts(self, tag=None):
"""Liệt kê tất cả prompt, có thể lọc theo tag."""
return self.storage.list(tag_filter=tag)
Sử dụng Prompt Registry trong ứng dụng
# Khởi tạo registry
registry = PromptRegistry(storage_backend=PostgresStorage())
# Đăng ký prompt
registry.register(
prompt_id="customer-support-v2",
template=support_template,
metadata={
"version": "2.1.0",
"author": "prompt-team",
"tags": ["customer-support", "production"],
"test_results": {"accuracy": 0.94, "red_team_score": 0.97}
}
)
# Sử dụng trong API handler
async def handle_customer_query(request):
context = build_context(request)
prompt, variant = registry.get(
"customer-support-v2",
context=context.__dict__,
user_id=request.user_id
)
response = await claude_client.messages.create(
model="claude-sonnet-4-20250514",
system=prompt,
messages=[{"role": "user", "content": request.message}]
)
# Log experiment metrics
registry.experiments.get("customer-support-v2", {}).log_result(
user_id=request.user_id,
variant=variant,
metrics={"response_time": response.usage.output_tokens}
)
return response
Chiến lược quản lý prompt trong team
Khi team có nhiều người cùng làm việc với prompt, cần quy trình rõ ràng:
- Prompt review process: Giống code review, mỗi thay đổi prompt cần ít nhất một người review trước khi merge
- Staging environment: Test prompt mới trong staging trước khi deploy lên production
- Gradual rollout: Deploy prompt mới cho 5% traffic trước, đo lường, rồi mới tăng dần
- Rollback plan: Luôn có khả năng rollback về phiên bản trước trong vòng vài phút
- Documentation: Mỗi prompt cần có doc mô tả mục đích, ràng buộc, và lý do thiết kế
Xử lý edge cases trong dynamic prompting
Dynamic prompt có thể gặp vấn đề khi các biến đầu vào bất thường:
Context quá dài
def truncate_context(context, max_tokens=2000):
"""Cắt ngắn context khi vượt quá giới hạn."""
estimated_tokens = len(context.split()) * 1.3
if estimated_tokens > max_tokens:
# Giữ phần đầu và phần cuối, bỏ phần giữa
words = context.split()
keep_count = int(max_tokens / 1.3)
half = keep_count // 2
truncated = ' '.join(words[:half]) + '
[... nội dung đã được tóm tắt ...]
' + ' '.join(words[-half:])
return truncated
return context
Biến bị thiếu hoặc rỗng
def safe_render(template, variables):
"""Render template với fallback cho biến thiếu."""
defaults = {
"role": "trợ lý AI thông minh",
"tone": "chuyên nghiệp và thân thiện",
"language": "Tiếng Việt",
"word_count": "phù hợp với nội dung",
}
# Merge defaults với variables, ưu tiên variables
merged = {**defaults, **{k: v for k, v in variables.items() if v}}
return template.render(**merged)
Prompt tham khảo cho thiết kế hệ thống
Tôi đang xây dựng hệ thống dynamic prompt cho ứng dụng sau:
- Loại ứng dụng: [Mô tả]
- Số lượng prompt templates: [Số lượng]
- Traffic dự kiến: [Requests/ngày]
- Team size: [Số người]
Hãy thiết kế:
1. Kiến trúc prompt registry phù hợp
2. Chiến lược A/B testing
3. Quy trình review và deploy prompt
4. Monitoring và alerting cho prompt quality
5. Rollback procedure
Ưu tiên đơn giản và pragmatic hơn là phức tạp.
Monitoring và Debugging Dynamic Prompts
Khi prompt được tạo động, debugging trở nên khó hơn vì bạn không thể nhìn thấy prompt cuối cùng chỉ bằng cách đọc code. Cần có hệ thống logging và monitoring chuyên biệt.
Prompt Logging
Ghi lại prompt cuối cùng được gửi đến model, kèm metadata về context đã dùng để tạo prompt:
import logging
import hashlib
prompt_logger = logging.getLogger("prompt_system")
def log_prompt_execution(prompt_id, rendered_prompt, context, response, metrics):
"""Ghi log đầy đủ cho mỗi lần thực thi prompt."""
log_entry = {
"prompt_id": prompt_id,
"prompt_hash": hashlib.sha256(rendered_prompt.encode()).hexdigest()[:12],
"prompt_length": len(rendered_prompt),
"context_keys": list(context.keys()),
"user_level": context.get("user_level"),
"task_type": context.get("task_type"),
"response_tokens": metrics.get("output_tokens"),
"latency_ms": metrics.get("latency_ms"),
"variant": metrics.get("variant", "default"),
}
prompt_logger.info("prompt_executed", extra=log_entry)
# Lưu prompt đầy đủ để debug (chỉ trong development)
if settings.DEBUG:
prompt_logger.debug(
"full_prompt",
extra={"prompt_text": rendered_prompt[:2000]}
)
Prompt Quality Monitoring
Theo dõi chất lượng prompt qua các metrics tổng hợp theo thời gian:
- Prompt length distribution: Prompt ngắn quá hoặc dài quá đều có thể là vấn đề. Theo dõi phân phối độ dài theo prompt_id.
- Template usage frequency: Template nào được dùng nhiều nhất? Template nào không bao giờ được dùng (có thể xóa)?
- Error rate by template: Template nào có tỷ lệ lỗi cao? Có thể template đó cần được cải thiện.
- A/B test convergence: Experiment nào đã có đủ data để kết luận? Experiment nào cần chạy thêm?
Alerting rules
Giúp tôi thiết lập alerting rules cho hệ thống dynamic prompt:
Metrics hiện có:
- prompt_render_time: Thời gian render template (ms)
- prompt_length: Số ký tự của prompt cuối cùng
- claude_error_rate: Tỷ lệ lỗi từ Claude API (%)
- user_satisfaction: Điểm hài lòng trung bình (1-5)
- follow_up_rate: Tỷ lệ user hỏi lại (%)
Với mỗi metric, đề xuất:
1. Ngưỡng cảnh báo (warning) và ngưỡng nghiêm trọng (critical)
2. Cửa sổ thời gian đánh giá (5 phút, 1 giờ, 1 ngày)
3. Hành động khuyến nghị khi alert trigger
4. Cách phân biệt anomaly thật vs false positive
Anti-patterns cần tránh
Khi xây dựng hệ thống dynamic prompt, có một số sai lầm phổ biến cần tránh:
Anti-pattern 1: Over-engineering
Không phải mọi prompt đều cần dynamic generation. Nếu prompt chỉ phục vụ một use case duy nhất và ít thay đổi, static prompt đơn giản hơn và dễ debug hơn. Chỉ chuyển sang dynamic khi có nhu cầu thực tế rõ ràng.
Anti-pattern 2: Quá nhiều biến
Template với 20+ biến trở nên khó hiểu và khó test. Nếu template cần nhiều biến như vậy, có thể bạn đang cố nhồi quá nhiều logic vào một prompt. Hãy cân nhắc chia thành nhiều prompt nhỏ hơn.
Anti-pattern 3: Bỏ qua fallback
Khi một biến trong template là null hoặc empty, prompt có thể bị hỏng cấu trúc. Luôn có giá trị mặc định cho mọi biến và validate template output trước khi gửi đến model.
Anti-pattern 4: Không test đủ combinations
Nếu template có 5 biến, mỗi biến có 3 giá trị khả dĩ, bạn có 243 combinations. Không cần test hết, nhưng cần test các combinations thường gặp nhất và các edge cases. Dùng property-based testing để tự động sinh combinations.
Anti-pattern 5: Quên tính chi phí token
Dynamic prompt dài hơn static prompt vì thêm context, examples, và instructions. Mỗi token thêm vào đều tốn tiền. Theo dõi prompt length và tối ưu khi cần — loại bỏ context không cần thiết, rút gọn instructions, giảm số ví dụ mẫu khi user đã quen với hệ thống.
Bước tiếp theo
Dynamic prompt generation chuyển prompt engineering từ việc viết tay thủ công sang một hệ thống có kiến trúc rõ ràng, testable, và scalable. Bắt đầu bằng cách chuyển 2-3 static prompt quan trọng nhất của bạn sang template, thêm context-aware logic, và thiết lập A/B testing cơ bản. Tìm hiểu thêm các pattern nâng cao tại Thư viện Nâng cao.
Bai viet co huu ich khong?
Bản quyền thuộc về tác giả. Vui lòng dẫn nguồn khi chia sẻ.





