Skip to content

Giao diện dòng lệnh & Chế độ tương tác

Bài học này phân tích cách guide_ai.py xây dựng giao diện dòng lệnh (CLI) linh hoạt, hỗ trợ cả chế độ tương tác và tham số dòng lệnh.

1. Tổng quan điểm vào

guide_ai.py là điểm vào chính của ứng dụng, hỗ trợ 2 chế độ:

Chế độKhi nàoƯu điểm
Tương tácKhông có đủ tham sốDễ sử dụng, có hướng dẫn
Dòng lệnhCó đầy đủ tham sốTự động hóa, scripting
python
# Xác định chế độ chạy
run_interactive = args.interactive or (args.provider is None and not args.no_ai)

2. Bộ phân tích tham số

2.1. Cấu trúc tham số

python
parser = argparse.ArgumentParser(
    description="Guide Generator - Tạo tài liệu hướng dẫn tự động",
    formatter_class=argparse.RawDescriptionHelpFormatter,
    epilog="""
Ví dụ:
  python guide_ai.py                                    # Chế độ tương tác
  python guide_ai.py --provider gemini --name free      # Dùng Gemini
  python guide_ai.py --no-ai --name test                # Không dùng AI
    """
)

2.2. Các nhóm tham số

Tham số chính:

python
parser.add_argument("--url", "-u", help="URL bắt đầu")
parser.add_argument("--name", "-n", help="Tên guide")
parser.add_argument("--title", "-t", help="Tiêu đề")
parser.add_argument("--provider", "-p", choices=["gemini", "openai", "none"])
parser.add_argument("--no-ai", action="store_true")

Tham số xác thực:

python
parser.add_argument("--save-auth", action="store_true", 
                    help="Mở browser để đăng nhập và lưu session")
parser.add_argument("--clear-auth", action="store_true")
parser.add_argument("--auth-status", action="store_true")

Tham số tạo test:

python
parser.add_argument("--generate-tests", action="store_true")
parser.add_argument("--test-type", choices=["unit", "integration", "both"])
parser.add_argument("--run-tests", action="store_true")

3. Hệ thống menu tương tác

3.1. Menu chính

python
def interactive_menu() -> dict:
    """Menu tương tác để cấu hình."""
    
    # Hiển thị header
    print("=" * 60)
    print("📚 GUIDE GENERATOR - Tạo tài liệu hướng dẫn tự động")
    print("=" * 60)
    
    # Hiển thị trạng thái auth
    print(f"🔐 {get_auth_status()}")
    
    # Hỏi mode: Tạo mới hay Replay
    mode_choice = prompt_choice(
        "🎯 Bạn muốn:",
        ["Tạo guide mới (record từ đầu)", "Dùng lại script đã record (replay)"],
        default=1
    )

3.2. Các hàm hỗ trợ

Hỏi Có/Không:

python
def prompt_yes_no(question: str, default: bool = True) -> bool:
    """Hỏi người dùng yes/no với default value."""
    suffix = " (Y/n): " if default else " (y/N): "
    while True:
        response = input(question + suffix).strip().lower()
        if not response:
            return default
        if response in ('y', 'yes', 'có', 'co'):
            return True
        if response in ('n', 'no', 'không', 'khong'):
            return False

Hỏi lựa chọn:

python
def prompt_choice(question: str, choices: list, default: int = 1) -> int:
    """Hỏi người dùng chọn từ danh sách."""
    print(question)
    for i, choice in enumerate(choices, 1):
        marker = " (mặc định)" if i == default else ""
        print(f"   [{i}] {choice}{marker}")
    
    while True:
        response = input(f"   Chọn [1-{len(choices)}]: ").strip()
        if not response:
            return default
        # Validate input...

4. Tính năng phát lại

4.1. Liệt kê các hướng dẫn đã tạo

python
def list_existing_guides() -> list:
    """Liệt kê tất cả các guides đã tạo trước đó."""
    output_dir = Path("output")
    guides = []
    
    # Duyệt qua hostname directories
    for hostname_dir in output_dir.iterdir():
        for guide_dir in hostname_dir.iterdir():
            script_path = guide_dir / "recorded_script.py"
            if script_path.exists():
                created_time = datetime.fromtimestamp(script_path.stat().st_mtime)
                guides.append((hostname_dir.name, guide_dir.name, script_path, created_time))
    
    # Sắp xếp theo thời gian (mới nhất trước)
    guides.sort(key=lambda x: x[3], reverse=True)
    return guides

4.2. Chọn hướng dẫn để phát lại

python
def select_existing_guide() -> dict:
    """Cho phép người dùng chọn guide để replay."""
    guides = list_existing_guides()
    
    print("📚 CÁC GUIDE ĐÃ TẠO:")
    for i, (hostname, guide_name, _, created_time) in enumerate(guides, 1):
        print(f"   [{i}] {hostname}/{guide_name}")
        print(f"       📅 {created_time.strftime('%Y-%m-%d %H:%M')}")
    
    # User chọn → Return config dict
    return {
        'mode': 'replay',
        'hostname': hostname,
        'guide_name': guide_name,
        'script_path': script_path,
        # ...
    }

5. Luồng cấu hình

5.1. Mẫu trả về Dict

Cả interactive_menu() và CLI đều trả về dict cùng format:

python
{
    'mode': 'new' | 'replay',
    'url': str,
    'name': str,
    'title': str,
    'provider': 'gemini' | 'openai' | 'none',
    'generate_tests': bool,
    'test_type': 'unit' | 'integration' | 'both',
    'run_tests': bool
}

5.2. Xử lý theo chế độ

python
if mode == 'replay':
    # Replay existing guide
    from src.orchestrator import replay_and_regenerate
    success = replay_and_regenerate(config, script_path)
else:
    # Create new guide
    success = orchestrate(config)

6. Tích hợp tạo test

6.1. Cấu hình test

python
def generate_tests_from_config(script_path, output_dir, test_type, provider, run_tests):
    """Generate tests từ recorded script."""
    
    # Convert string to enum
    test_type_enum = {
        "unit": TestType.UNIT,
        "integration": TestType.INTEGRATION,
        "both": TestType.BOTH
    }[test_type]
    
    # Create config
    test_config = TestGenerationConfig(
        script_path=script_path,
        output_dir=output_dir / "tests",
        test_type=test_type_enum,
        use_ai=(provider != "none"),
        # ...
    )
    
    # Generate
    orchestrator = TestOrchestrator()
    result = orchestrator.generate_tests_from_script(script_path, test_config)

7. Thực hành tốt

7.1. Nguyên tắc trải nghiệm người dùng

Nguyên tắcÁp dụng
Giá trị mặc định hợp lýURL mặc định, tên tự động theo timestamp
Tiết lộ dần dầnHỏi từng bước, không làm người dùng choáng ngợp
Xác nhậnHiển thị tóm tắt trước khi bắt đầu
Thoát nhẹ nhàngCho phép hủy ở mọi bước

7.2. Tổ chức mã nguồn

guide_ai.py
├── Argument Parser (CLI)
├── Helper Functions
│   ├── prompt_yes_no()
│   ├── prompt_choice()
│   └── list_existing_guides()
├── Interactive Menu
│   ├── interactive_menu()
│   └── select_existing_guide()
├── Test Generation
│   └── generate_tests_from_config()
└── Main Entry Point
    └── main()

8. Ví dụ sử dụng

Chế độ dòng lệnh

bash
# Tạo guide mới với Gemini
python guide_ai.py --provider gemini --name login_guide --url https://example.com

# Không dùng AI
python guide_ai.py --no-ai --name quick_test

# Tạo guide + tests
python guide_ai.py --provider gemini --name full_guide --generate-tests --run-tests

Lệnh xác thực

bash
# Lưu session đăng nhập
python guide_ai.py --save-auth --url https://portal.inet.vn

# Kiểm tra trạng thái
python guide_ai.py --auth-status

# Xóa session
python guide_ai.py --clear-auth

Tổng kết

guide_ai.py thiết kế CLI theo nguyên tắc:

  • Hai chế độ: Tương tác cho người mới, dòng lệnh cho tự động hóa
  • Module hóa: Tách biệt phân tích, hỏi đáp, thực thi
  • Mở rộng được: Dễ thêm tùy chọn mới (xác thực, test)
  • Thân thiện: Giao diện tiếng Việt, phản hồi rõ ràng

Bài học tiếp theo

Xác thực & Quản lý phiên

Internal documentation for iNET Portal