paint-brush
Cách tận dụng LLM để phát triển phần mềm hiệu quả và có thể mở rộngtừ tác giả@bishalbaral
521 lượt đọc
521 lượt đọc

Cách tận dụng LLM để phát triển phần mềm hiệu quả và có thể mở rộng

từ tác giả Bishal11m2024/08/04
Read on Terminal Reader

dài quá đọc không nổi

Giám đốc điều hành YCombinator Garry Tan đã tweet một bài đăng của một thành viên cộng đồng YCombinator Reddit về việc viết mã với Claude 3.5 Sonnet. Bài đăng nhấn mạnh tầm quan trọng của việc đưa ra các quyết định đúng đắn về kiến trúc và cơ sở hạ tầng như một phần quan trọng trong việc sử dụng LLM hàng ngày của họ.
featured image - Cách tận dụng LLM để phát triển phần mềm hiệu quả và có thể mở rộng
Bishal HackerNoon profile picture
0-item
1-item

Gần đây, người dùng trên X và Reddit đã báo cáo rằng việc viết mã bằng Claude 3.5 Sonnet khiến họ cảm thấy “rất mạnh mẽ”. Một bài đăng đặc biệt thu hút sự chú ý là dòng tweet của Giám đốc điều hành YCombinator, Garry Tan.


Garry đã chia sẻ bài đăng sau đây của một trong những thành viên cộng đồng Reddit YCombinator của họ về cách sử dụng Claude 3.5 Sonnet đã tăng năng suất của họ lên gấp 10 lần trong khi triển khai các tính năng phổ biến.


Bài đăng cũng nhấn mạnh tầm quan trọng của việc đưa ra các quyết định đúng đắn về kiến trúc và cơ sở hạ tầng như một phần quan trọng trong việc sử dụng LLM hàng ngày của họ.


Mặc dù các LLM như Claude 3.5 mang lại những lợi ích vượt trội nhưng chúng vẫn có những hạn chế trong việc duy trì bộ nhớ và ngữ cảnh. Một số chiến lược phát triển có thể được sử dụng để giải quyết những hạn chế này. Các chiến lược này xoay quanh nền tảng phát triển phần mềm mà tất cả các nhà phát triển đều trau dồi kinh nghiệm nhưng thường dễ bị bỏ sót khi nhắc LLM bằng tiếng Anh đơn giản.


Việc áp dụng các nguyên tắc cơ bản tương tự mà các nhà phát triển sử dụng hàng ngày, điều mà tác giả Reddit gọi là các quyết định về kiến trúc, cho các tương tác LLM có thể tạo ra mã có tính mô-đun cao, có khả năng mở rộng và được ghi chép đầy đủ.


Sau đây là một số nguyên tắc mã hóa và phương pháp phát triển chính có thể áp dụng để phát triển phần mềm được hỗ trợ LLM, cùng với các ví dụ thực tế trong Python:

Tất cả lời nhắc trong ví dụ đều được sử dụng với Claude Sonnet 3.5.

Kiến trúc dựa trên thành phần

Để mô tả từng thành phần logic cho LLM dễ dàng hơn và có được các thành phần chính xác, hãy chia cơ sở mã thành các thành phần nhỏ, được xác định rõ ràng.

 # database.py class Database: def __init__(self, sql_connection_string): .... def query(self, sql): .... # user_service.py class UserService: def __init__(self, database): self.db = database def get_user(self, user_id): return self.db.query(f"SELECT * FROM users WHERE id = {user_id}") # main.py db = Database("sql_connection_string") user_service = UserService(db) user = user_service.get_user(123)

Lớp trừu tượng

Để ẩn các triển khai phức tạp, hãy sử dụng các lớp trừu tượng và tập trung vào các lớp trừu tượng ở cấp độ cao hơn bằng cách sử dụng thông tin chi tiết cho từng thành phần được ghi lại trong quá trình thực hiện.

 # top-level abstraction class BankingSystem: def __init__(self): self._account_manager = AccountManager() self._transaction_processor = TransactionProcessor() def create_account(self, acct_number: str, owner: str) -> None: self._account_manager.create_account(acct_number, owner) def process_transaction(self, acct_number: str, transaction_type: str, amount: float) -> None: account = self._account_manager.get_account(acct_number) self._transaction_processor.process(account, transaction_type, amount) # mid-level abstractions class AccountManager: def __init__(self): def create_account(self, acct_number: str, owner: str) -> None: def get_account(self, acct_number: str) -> 'Account': class TransactionProcessor: def process(self, account: 'Account', transaction_type: str, amount: float) -> None: # lower-level abstractions class Account(ABC): .... class Transaction(ABC): .... # concrete implementations class SavingsAccount(Account): .... class CheckingAccount(Account): .... class DepositTransaction(Transaction): .... class WithdrawalTransaction(Transaction): .... # lowest-level abstraction class TransactionLog: .... # usage focuses on the high-level abstraction cart = ShoppingCart() cart.add_item(Item("Book", 15)) cart.add_item(Item("Pen", 2)) total = cart.get_total()

Định nghĩa giao diện sạch

Để thực hiện các nhiệm vụ dễ quản lý hơn khi tìm kiếm trợ giúp từ LLM, hãy xác định giao diện rõ ràng cho từng thành phần và tập trung triển khai tất cả chúng một cách riêng biệt.

 class PaymentProcessor(ABC): @abstractmethod def process_payment(self, amount: float, card_no: str) -> bool: .... class StripeProcessor(PaymentProcessor): # stripe specific implementation def process_payment(self, amount: float, card_no: str) -> bool: .... class PayPalProcessor(PaymentProcessor): # paypal specific implementation def process_payment(self, amount: float, card_no: str) -> bool: ....

Nguyên tắc trách nhiệm duy nhất

Để ngăn ngừa ảo giác và giới hạn phạm vi, hãy tập trung vào từng phần nhỏ một và đảm bảo mỗi lớp/chức năng có một trách nhiệm duy nhất, được xác định rõ ràng. Phát triển dần dần để có nhiều quyền kiểm soát hơn đối với mã được tạo.

 class UserManager: # user creation logic def create_user(self, username, email): ... class EmailService: # send welcome email logic def send_welcome_email(self, email): .... class NotificationService: # send sms notification def send_sms(self, username, email): ... # Usage user_manager = UserManager() email_svc = EmailService() user = user_manager.create_user("hacker", "[email protected]") email_svc.send_welcome_email("[email protected]")

Quy ước đặt tên nhất quán

Để đơn giản hóa việc mô tả cấu trúc mã cho LLM và hiểu các đề xuất của chúng, hãy sử dụng các quy tắc đặt tên rõ ràng và nhất quán.

 # classes: PascalCase class UserAccount: pass # functions and variables: snake_case def calculate_total_price(item_price, quantity): total_cost = item_price * quantity return total_cost # constants: UPPERCASE_WITH_UNDERSCORES MAX_LOGIN_ATTEMPTS = 3 # private methods/variables: prefix with underscore class DatabaseConnection: def __init__(self): self._connection = None def _connect_to_database(self): pass

Tạo mẫu mã

Để tạo các triển khai cụ thể dựa trên yêu cầu, hãy tạo mã khung cho các cấu trúc mã phổ biến và sử dụng chúng làm mã khởi động.

 # Todo item - pydantic Model class TodoItem(BaseModel): id: Optional[int] = None title: str description: Optional[str] = None completed: bool = False todo_db = [<insert mock data>] @app.get("/todos", response_model=List[TodoItem]) async def get_todos(): # TODO: retrieve all todos @app.get("/todos/{todo_id}", response_model=TodoItem) async def get_todo(todo_id: int): # TODO: retrieve specific todo @app.post("/todos", response_model=TodoItem) async def create_todo(todo: TodoItem): # TODO: create todo @app.put("/todos/{todo_id}", response_model=TodoItem) async def update_todo(todo_id: int, todo: TodoItem): # TODO: update todo @app.delete("/todos/{todo_id}") async def delete_todo(todo_id: int): # TODO: delete todo

Phát triển theo hướng tài liệu

Để giúp hướng dẫn LLM, hãy viết tài liệu ngắn gọn cho từng thành phần trước khi triển khai. Hơn nữa, hãy tạo các chuỗi tài liệu có thể hướng dẫn lời nhắc trong tương lai bằng chính LLM.


lời nhắc:

 Use a Documentation Driven Development approach to write clear, concise docstrings for the following python function calculate_discount(price, discount_percentage) takes in - price (float), original price of the item. - discount_percentage (float), discount percentage range(0-100). returns - price after discount (float) raises - ValueError, when discount_percentage is out of range example - calculate_discount(100, 10) -> 10.0


phản ứng:

 def calculate_discount(price: float, discount_percent: float) -> float: """ Calculate the discounted price of an item. Args: price (float): original price for the item. discount_percentage (float): discount percentage range(0-100). Returns: float: The price after applying the discount. Raises: ValueError: If discount_percentage is not between 0 and 100. Example: >>> calculate_discount(100, 20) 80.0 """ if not 0 <= discount_percent <= 100: raise ValueError("Discount percent must be between 0 and 100") discount_amount = price * (discount_percent / 100) return price - discount_amount

Hướng phát triển thử nghiệm

Để giúp LLM triển khai và đặc biệt là xử lý các trường hợp khó khăn, hãy tự viết bài kiểm tra hoặc sử dụng LLM để làm việc đó trước khi triển khai chức năng thực tế. LLM không chạy mã nội bộ nhưng việc kiểm tra trước để đảm bảo mã được tạo đáp ứng các yêu cầu về chức năng có thể hữu ích trong việc phát hiện lỗi trong mã do LLM tạo.


trường hợp thử nghiệm:

 def is_palindrome(s: str) -> bool: """check if string is palindrome.""" return s == s[::-1] class TestPalindrome(unittest.TestCase): def test_palindrome(self): self.assertTrue(is_palindrome("racecar")) self.assertTrue(is_palindrome("A man a plan a canal Panama")) self.assertFalse(is_palindrome("hello")) self.assertTrue(is_palindrome("")) # Edge case: empty string


lời nhắc:

 given the test case <insert test>, use Document Driven Development to write a function for TestPalindrome


phản ứng:

 def is_palindrome(s: str) -> bool: """ Check if a string is a palindrome. A palindrome is a word, phrase, number, or other sequence of characters that reads the same forward and backward, ignoring spaces, punctuation, and capitalization. Args: s (str): The input string to check. Returns: bool: True if the input is a palindrome, False otherwise. Examples: >>> is_palindrome("racecar") True >>> is_palindrome("A man a plan a canal Panama") True >>> is_palindrome("hello") False >>> is_palindrome("") True """ # Remove non-alphanumeric characters and convert to lowercase cleaned = ''.join(char.lower() for char in s if char.isalnum()) # Compare the cleaned string with its reverse return cleaned == cleaned[::-1]

Thư viện mẫu thiết kế

Để thảo luận về nhiều chi tiết triển khai với LLM, hãy duy trì một thư viện các mẫu thiết kế thường được sử dụng để tham khảo.

 # Singleton pattern class DatabaseConnection: _instance = None def __new__(cls): if cls._instance is None: cls._instance = super().__new__(cls) # initialize database connection return cls._instance # Factory pattern class AnimalFactory: @staticmethod def create_animal(animal_type): if animal_type == "dog": return Dog() elif animal_type == "cat": return Cat() else: raise ValueError("Unknown animal type") # Observer pattern class Subject: def __init__(self): self._observers = [] def attach(self, observer): self._observers.append(observer) def detach(self, observer): self._observers.remove(observer) def notify(self): for observer in self._observers: observer.update() # Adapter pattern class LLMAdapter: def __init__(self, llm_service): self.llm_service = llm_service def generate_code(self, prompt): llm_response = self.llm_service.complete(prompt) return self.extract_code(llm_response) def extract_code(self, response): pass

Danh sách kiểm tra đánh giá mã

Để đảm bảo chất lượng và tính nhất quán, hãy tạo danh sách kiểm tra để xem xét mã do LLM tạo.

 # Code Review Checklist ## Functionality - [ ] Code performs the intended task correctly - [ ] Edge cases are handled appropriately ## Code Quality - [ ] Code follows project's style guide - [ ] Variable and function names are descriptive and consistent - [ ] No unnecessary comments or dead code ## Performance - [ ] Code is optimized for efficiency - [ ] No potential performance bottlenecks ## Security - [ ] Input validation is implemented - [ ] Sensitive data is handled securely ## Testing - [ ] Unit tests are included and pass - [ ] Edge cases are covered in tests ## Documentation - [ ] Functions and classes are properly documented - [ ] Complex logic is explained in comments

Nhắc nhở mô-đun

LLM hoạt động tốt nhất với cấu trúc xác định, vì vậy hãy phát triển chiến lược chia các nhiệm vụ mã hóa thành các lời nhắc nhỏ hơn. Thực hiện theo cách tiếp cận có tổ chức sẽ giúp tạo mã hoạt động mà không nhắc LLM sửa lại mã đã tạo nhiều lần.


lời nhắc:

 I need to implement a function to calculate the Fibonacci number sequence using a Document Driven Development approach. 1. Purpose: function that generates the Fibonacci sequence up to a given number of terms. 2. Interface: def fibonacci_seq(n: int) -> List[int]: """ generate Fibonacci sequence up to n terms. Args: n (int): number of terms in the sequence Returns: List[int]: fibonacci sequence """ 3. Key Functionalities: - handle input validation (n should always be a positive integer) - generate the sequence starting with 0 and 1 - each subsequent number is the sum of two preceding ones - return the sequence as a list 4. Implementation Details: - use a loop to generate the sequence - store the sequence in a list - optimize for memory by only keeping the last two numbers in memory if needed 5. Test Cases: - fibonacci_seq(0) should return [] - fibonacci_seq(1) should return [0] - fibonacci_seq(5) should return [0, 1, 1, 2, 3]

Mặc dù tất cả các ví dụ trên có vẻ đơn giản, nhưng việc tuân theo các phương pháp thực hành nền tảng như kiến trúc mô-đun và kỹ thuật nhanh chóng hiệu quả cũng như áp dụng cách tiếp cận có cấu trúc vững chắc trong quá trình phát triển được hỗ trợ bởi LLM sẽ tạo ra sự khác biệt lớn về quy mô. Bằng cách triển khai các phương pháp này, nhiều nhà phát triển hơn có thể tối đa hóa lợi ích của việc sử dụng LLM, giúp nâng cao năng suất và chất lượng mã.


LLM là công cụ mạnh mẽ hoạt động tốt nhất khi được hướng dẫn bởi các nguyên tắc công nghệ phần mềm dễ bị bỏ qua. Việc tiếp thu chúng có thể là sự khác biệt giữa mã được tạo ra một cách trang nhã và Quả bóng bùn lớn được tạo ngẫu nhiên.


Mục tiêu của bài viết này là khuyến khích các nhà phát triển luôn ghi nhớ những thực tiễn này khi sử dụng LLM để tạo ra mã chất lượng cao và tiết kiệm thời gian trong tương lai. Khi LLM tiếp tục được cải thiện, các nguyên tắc cơ bản sẽ càng trở nên quan trọng hơn để tận dụng tốt nhất chúng.


Để tìm hiểu sâu hơn về các nguyên tắc phát triển phần mềm, hãy xem cuốn sách giáo khoa cổ điển này: Kiến trúc sạch: Hướng dẫn về cấu trúc và thiết kế phần mềm cho thợ thủ công của Robert C. Martin.


Nếu bạn thích bài viết này, hãy theo dõi bài viết tiếp theo nơi chúng tôi đi sâu vào quy trình làm việc chi tiết để phát triển được hỗ trợ bởi LLM. Hãy chia sẻ bất kỳ khái niệm nào khác mà bạn cho là quan trọng trong phần bình luận! Cảm ơn.