目录8.1 从“函数”到“对象”的思维升级8.1.1 为什么需要对象8.1.2 类与对象蓝图与实例8.2 定义第一个 AI 相关的类8.2.1 最简单的类结构8.2.2 添加属性记录模型的特征8.2.3 添加方法让对象能“做事”8.3 构造函数 __init__ 与属性详解8.3.1 带默认值的属性8.3.2 类属性 vs 实例属性8.4 封装把内部细节藏起来8.5 继承基于通用模型创建专用模型8.5.1 基本继承8.5.2 重写方法改变父类的行为8.5.3 多继承了解即可8.6 多态不同的对象相同的方法名8.7 特殊方法魔术方法让对象更像“原生”数据8.7.1 __str__ 和 __repr__定义对象的字符串表示8.7.2 __len__让 len() 可用8.7.3 __call__让对象像函数一样被调用8.8 综合实战构建一个可扩展的 LLM 客户端系统8.9 本章小结之前我们学习了函数和模块可以把一段代码封装成可复用的“工具”。但在更复杂的 AI 应用中比如一个完整的对话机器人、多模型调度器、工具调用链我们需要更高级的组织方式把数据和操作数据的方法打包在一起这就是面向对象编程OOP。本章会带你用 AI 大模型相关的例子轻松理解类、对象、继承等概念。8.1 从“函数”到“对象”的思维升级8.1.1 为什么需要对象假设你要写一个处理 OpenAI API 调用的程序。用函数式写法你可能会这样def call_llm(prompt, model, temperature): # 调用 API 的逻辑 return response def count_tokens(text): return len(text.split()) def estimate_cost(model, tokens): # 根据模型计算费用 return cost但缺点很明显model、temperature这些参数要反复传递而且不同用户的不同模型配置难以管理。如果能把“一个模型实例”的所有属性模型名、温度、最大 token和它的行为调用、计费、token 统计打包在一起代码会清晰很多。8.1.2 类与对象蓝图与实例类一个蓝图或模板定义了一类事物应该有什么属性数据和方法能做什么。对象根据蓝图创建出来的具体实例每个对象可以有不同的属性值。类比类就像是汽车的设计图纸对象就是根据图纸造出来的一辆辆真车。每辆车有自己的颜色、车牌号但它们都遵循同一个设计能加速、刹车。8.2 定义第一个 AI 相关的类8.2.1 最简单的类结构class LLM: 大语言模型类最简单的版本 pass # 创建对象 my_model LLM() print(type(my_model)) # class __main__.LLM8.2.2 添加属性记录模型的特征属性就是属于某个对象的数据。class LLM: def __init__(self, name, context_length): 构造函数在创建对象时自动调用用于初始化属性 self.name name # 实例属性 self.context_length context_length # 创建两个不同的模型对象 gpt4 LLM(gpt-4, 8192) claude LLM(claude-3, 200000) print(gpt4.name) # gpt-4 print(claude.context_length) # 200000__init__是 Python 中的构造函数第一个参数必须是self代表对象本身。self.name name表示给这个对象添加一个叫name的属性并把它赋值为传入的参数。8.2.3 添加方法让对象能“做事”方法就是定义在类内部的函数第一个参数也是self。class LLM: def __init__(self, name, context_length, price_per_1k): self.name name self.context_length context_length self.price_per_1k price_per_1k def estimate_cost(self, input_tokens, output_tokens): 估算本次调用的费用美元 total_tokens input_tokens output_tokens return total_tokens / 1000 * self.price_per_1k def can_handle(self, prompt_length): 检查提示词长度是否在上下文限制内 return prompt_length self.context_length # 使用 gpt4 LLM(gpt-4, 8192, 0.03) cost gpt4.estimate_cost(1500, 300) print(f费用: ${cost}) # 费用: $0.054 print(gpt4.can_handle(10000)) # False注意调用方法时self不需要手动传递Python 会自动把gpt4作为self传进去。8.3 构造函数__init__与属性详解8.3.1 带默认值的属性class Conversation: def __init__(self, system_prompt你是AI助手, modelgpt-3.5): self.system_prompt system_prompt self.model model self.messages [] # 存储对话历史 def add_user_message(self, content): self.messages.append({role: user, content: content}) def add_assistant_message(self, content): self.messages.append({role: assistant, content: content}) def show_history(self): for msg in self.messages: print(f{msg[role]}: {msg[content]}) # 创建对话 chat Conversation(你是一位Python专家) chat.add_user_message(如何定义类) chat.add_assistant_message(用class关键字...) chat.show_history()8.3.2 类属性 vs 实例属性在Python中类属性是直接定义在类体中的变量被该类的所有实例共享通过类名.属性或实例.属性访问但实例修改时通常只创建实例属性不会影响类属性而实例属性是在实例方法内通过self.属性定义的每个实例独立拥有自己的副本修改实例属性不会影响其他实例或类属性。简单区分类属性属于“类蓝图”实例属性属于“每个具体对象”。实例属性每个对象独有的如上例中的self.name。类属性属于类本身所有对象共享的。class LLM: # 类属性记录所有已知模型的计数 total_models_created 0 def __init__(self, name): self.name name LLM.total_models_created 1 # 每次创建对象加 1 print(LLM.total_models_created) # 0 gpt LLM(gpt-4) claude LLM(claude-3) print(LLM.total_models_created) # 28.4 封装把内部细节藏起来封装是指把对象的内部状态属性和实现细节隐藏起来只通过公开的方法与外界交互。Python通过命名约定来实现“私有”单下划线_name表示“受保护的”外部不应直接访问但依然可以。双下划线__name名称修饰外部不能直接访问。class APIClient: def __init__(self, api_key): self.__api_key api_key # 私有属性 self._base_url https://api.openai.com # 受保护 def call(self, prompt): # 内部使用 __api_key 发起请求 return f使用密钥 {self.__api_key[:5]}... 调用成功回复{prompt} client APIClient(sk-123456) print(client.call(Hello)) # print(client.__api_key) # AttributeError print(client._base_url) # 可以访问但约定不要这样做封装的好处你可以随时改变内部实现如更换 API 提供商只要公开方法签名不变调用方代码完全不需要修改。8.5 继承基于通用模型创建专用模型继承允许你定义一个子类它自动拥有父类的所有属性和方法并可以增加或重写覆盖一些功能。8.5.1 基本继承class BaseLLM: def __init__(self, name, context_length): self.name name self.context_length context_length def generate(self, prompt): return f{self.name} 生成: {prompt} # 子类支持函数调用的模型 class FunctionCallingLLM(BaseLLM): def call_function(self, func_name, args): return f{self.name} 正在调用函数 {func_name}参数 {args} gpt4 FunctionCallingLLM(gpt-4, 8192) print(gpt4.generate(Hello)) # 继承的方法 print(gpt4.call_function(get_weather, {city: Beijing})) # 子类新方法8.5.2 重写方法改变父类的行为class GPT4(BaseLLM): def generate(self, prompt): # 调用父类方法并补充内容 base_response super().generate(prompt) return base_response [额外使用高精度计算] model GPT4(gpt-4, 8192) print(model.generate(讲个笑话)) # 输出gpt-4 生成: 讲个笑话 [额外使用高精度计算]8.5.3 多继承了解即可Python 支持一个子类继承多个父类但容易复杂。AI 框架中较少见。class Streamable: def stream(self): return 流式输出 class Cacheable: def cache(self): return 缓存命中 class AdvancedLLM(BaseLLM, Streamable, Cacheable): pass adv AdvancedLLM(claude, 100000) print(adv.stream())8.6 多态不同的对象相同的方法名多态允许不同类的对象对同一个方法名做出不同的响应。在 AI 中你可以定义一个统一的generate接口然后不同模型类各自实现它。class OpenAIModel: def generate(self, prompt): return OpenAI 回复: prompt class AnthropicModel: def generate(self, prompt): return Anthropic 回复: prompt def chat(model, prompt): print(model.generate(prompt)) gpt OpenAIModel() claude AnthropicModel() chat(gpt, 你好) # OpenAI 回复: 你好 chat(claude, 你好) # Anthropic 回复: 你好8.7 特殊方法魔术方法让对象更像“原生”数据在Python中有一类以双下划线开头和结尾的方法比如init、str、len它们被称为“魔术方法”。魔术方法不是让你直接调用的而是 Python 在特定场景下自动调用的。通过实现这些方法你可以让自己的类实例表现得像 Python 内置的列表、字符串、数字一样支持len()、str()、等操作。零基础理解可以把魔术方法理解为“潜规则”或“约定”。比如当Python看到len(x)时它会自动去调用x的len方法。你只要在类里写好了len方法Python 就知道你的对象也能问“有多长”。常用魔术方法举例init初始化方法。当你创建对象时比如p Person()Python 自动调用它用来设置对象的初始属性。str字符串表示。当你使用print(对象)或str(对象)时Python 自动调用它返回一个“给人看”的友好字符串。repr开发时用的字符串表示。在交互环境中直接输入对象名时显示通常返回一个可以用来重建对象的表达式。len长度。当你调用len(对象)时Python自动调用它返回一个整数。add加法。当你使用对象1 对象2时Python自动调用左边对象的add方法把右边的对象传进去。8.7.1__str__和__repr__定义对象的字符串表示class LLM: def __init__(self, name, context): self.name name self.context context def __str__(self): return fLLM({self.name}, ctx{self.context}) model LLM(gpt-4, 8192) print(model) # LLM(gpt-4, ctx8192)8.7.2__len__让len()可用class ConversationHistory: def __init__(self): self.messages [] def add(self, msg): self.messages.append(msg) def __len__(self): return len(self.messages) hist ConversationHistory() hist.add(hello) hist.add(world) print(len(hist)) # 28.7.3__call__让对象像函数一样被调用class TemperatureScaler: def __init__(self, factor1.2): self.factor factor def __call__(self, temperature): return temperature * self.factor scale TemperatureScaler(1.5) print(scale(0.7)) # 1.05对象名后面加括号就像函数调用这在 AI 框架中常用于配置某些可调用的参数变换。8.8 综合实战构建一个可扩展的 LLM 客户端系统我们将用面向对象的方法设计一个支持多厂商、带缓存、带计费的模型客户端。import hashlib import time # ---------- 1. 基础模型接口抽象基类但不严格要求---------- class BaseLLM: def __init__(self, name, price_per_1k): self.name name self.price_per_1k price_per_1k self.total_cost 0.0 def generate(self, prompt, **kwargs): 子类必须实现具体调用逻辑 raise NotImplementedError def _record_cost(self, input_tokens, output_tokens): cost (input_tokens output_tokens) / 1000 * self.price_per_1k self.total_cost cost return cost # ---------- 2. 具体模型实现 ---------- class OpenAIClient(BaseLLM): def __init__(self, api_key, model_namegpt-3.5-turbo): super().__init__(model_name, price_per_1k0.002) self.api_key api_key def generate(self, prompt, temperature0.7): # 模拟 API 调用实际会用 requests 库 print(f[OpenAI] 调用 {self.name}temperature{temperature}) # 模拟 token 计数 input_tokens len(prompt) // 4 output_text fOpenAI 回复{prompt} output_tokens len(output_text) // 4 cost self._record_cost(input_tokens, output_tokens) return { text: output_text, input_tokens: input_tokens, output_tokens: output_tokens, cost: cost } class AnthropicClient(BaseLLM): def __init__(self, api_key, model_nameclaude-3): super().__init__(model_name, price_per_1k0.025) self.api_key api_key def generate(self, prompt, temperature0.7): print(f[Anthropic] 调用 {self.name}temperature{temperature}) input_tokens len(prompt) // 4 output_text fClaude 回复{prompt} output_tokens len(output_text) // 4 cost self._record_cost(input_tokens, output_tokens) return { text: output_text, input_tokens: input_tokens, output_tokens: output_tokens, cost: cost } # ---------- 3. 带缓存的装饰器模式简化 ---------- class CachedLLM: def __init__(self, llm_client): self.llm llm_client self.cache {} def generate(self, prompt, **kwargs): key hashlib.md5(f{prompt}_{kwargs}.encode()).hexdigest() if key in self.cache: print(缓存命中) return self.cache[key] else: result self.llm.generate(prompt, **kwargs) self.cache[key] result return result # ---------- 4. 使用 ---------- if __name__ __main__: # 创建原始客户端 openai OpenAIClient(api_keysk-xxx, model_namegpt-4) # 增加缓存功能 cached_openai CachedLLM(openai) # 第一次调用 res1 cached_openai.generate(讲个笑话, temperature0.8) print(res1[text]) print(f花费: ${res1[cost]:.4f}) # 第二次调用相同 prompt会命中缓存 res2 cached_openai.generate(讲个笑话, temperature0.8) print(res2[text]) print(f总成本: {openai.total_cost})运行上述代码输出如下内容tianpengDESKTOP-4L1UF5S:~/my-ai-service$ poetry run python src/my_ai_service/loop.py [OpenAI] 调用 gpt-4temperature0.8 OpenAI 回复讲个笑话 花费: $0.0000 缓存命中 OpenAI 回复讲个笑话 总成本: 8e-06 tianpengDESKT8.9 本章小结概念含义AI 示例类 class设计蓝图class LLM:对象 instance根据类创建的具体实例gpt4 LLM(gpt-4)属性 attribute对象的数据self.name,self.context_length方法 method对象的行为def generate(self, prompt):__init__构造函数初始化对象设置 API 密钥、默认温度封装隐藏内部细节私有属性__api_key继承子类复用父类代码class FunctionCallingLLM(BaseLLM):多态不同对象相同方法名不同行为model.generate(prompt)对不同模型调不同的实现魔术方法让对象支持Python内置操作__str__,__len__,__call__
【AI大模型应用开发工程师特训笔记】第04讲(第8章):面向对象编程
发布时间:2026/5/29 5:45:33
目录8.1 从“函数”到“对象”的思维升级8.1.1 为什么需要对象8.1.2 类与对象蓝图与实例8.2 定义第一个 AI 相关的类8.2.1 最简单的类结构8.2.2 添加属性记录模型的特征8.2.3 添加方法让对象能“做事”8.3 构造函数 __init__ 与属性详解8.3.1 带默认值的属性8.3.2 类属性 vs 实例属性8.4 封装把内部细节藏起来8.5 继承基于通用模型创建专用模型8.5.1 基本继承8.5.2 重写方法改变父类的行为8.5.3 多继承了解即可8.6 多态不同的对象相同的方法名8.7 特殊方法魔术方法让对象更像“原生”数据8.7.1 __str__ 和 __repr__定义对象的字符串表示8.7.2 __len__让 len() 可用8.7.3 __call__让对象像函数一样被调用8.8 综合实战构建一个可扩展的 LLM 客户端系统8.9 本章小结之前我们学习了函数和模块可以把一段代码封装成可复用的“工具”。但在更复杂的 AI 应用中比如一个完整的对话机器人、多模型调度器、工具调用链我们需要更高级的组织方式把数据和操作数据的方法打包在一起这就是面向对象编程OOP。本章会带你用 AI 大模型相关的例子轻松理解类、对象、继承等概念。8.1 从“函数”到“对象”的思维升级8.1.1 为什么需要对象假设你要写一个处理 OpenAI API 调用的程序。用函数式写法你可能会这样def call_llm(prompt, model, temperature): # 调用 API 的逻辑 return response def count_tokens(text): return len(text.split()) def estimate_cost(model, tokens): # 根据模型计算费用 return cost但缺点很明显model、temperature这些参数要反复传递而且不同用户的不同模型配置难以管理。如果能把“一个模型实例”的所有属性模型名、温度、最大 token和它的行为调用、计费、token 统计打包在一起代码会清晰很多。8.1.2 类与对象蓝图与实例类一个蓝图或模板定义了一类事物应该有什么属性数据和方法能做什么。对象根据蓝图创建出来的具体实例每个对象可以有不同的属性值。类比类就像是汽车的设计图纸对象就是根据图纸造出来的一辆辆真车。每辆车有自己的颜色、车牌号但它们都遵循同一个设计能加速、刹车。8.2 定义第一个 AI 相关的类8.2.1 最简单的类结构class LLM: 大语言模型类最简单的版本 pass # 创建对象 my_model LLM() print(type(my_model)) # class __main__.LLM8.2.2 添加属性记录模型的特征属性就是属于某个对象的数据。class LLM: def __init__(self, name, context_length): 构造函数在创建对象时自动调用用于初始化属性 self.name name # 实例属性 self.context_length context_length # 创建两个不同的模型对象 gpt4 LLM(gpt-4, 8192) claude LLM(claude-3, 200000) print(gpt4.name) # gpt-4 print(claude.context_length) # 200000__init__是 Python 中的构造函数第一个参数必须是self代表对象本身。self.name name表示给这个对象添加一个叫name的属性并把它赋值为传入的参数。8.2.3 添加方法让对象能“做事”方法就是定义在类内部的函数第一个参数也是self。class LLM: def __init__(self, name, context_length, price_per_1k): self.name name self.context_length context_length self.price_per_1k price_per_1k def estimate_cost(self, input_tokens, output_tokens): 估算本次调用的费用美元 total_tokens input_tokens output_tokens return total_tokens / 1000 * self.price_per_1k def can_handle(self, prompt_length): 检查提示词长度是否在上下文限制内 return prompt_length self.context_length # 使用 gpt4 LLM(gpt-4, 8192, 0.03) cost gpt4.estimate_cost(1500, 300) print(f费用: ${cost}) # 费用: $0.054 print(gpt4.can_handle(10000)) # False注意调用方法时self不需要手动传递Python 会自动把gpt4作为self传进去。8.3 构造函数__init__与属性详解8.3.1 带默认值的属性class Conversation: def __init__(self, system_prompt你是AI助手, modelgpt-3.5): self.system_prompt system_prompt self.model model self.messages [] # 存储对话历史 def add_user_message(self, content): self.messages.append({role: user, content: content}) def add_assistant_message(self, content): self.messages.append({role: assistant, content: content}) def show_history(self): for msg in self.messages: print(f{msg[role]}: {msg[content]}) # 创建对话 chat Conversation(你是一位Python专家) chat.add_user_message(如何定义类) chat.add_assistant_message(用class关键字...) chat.show_history()8.3.2 类属性 vs 实例属性在Python中类属性是直接定义在类体中的变量被该类的所有实例共享通过类名.属性或实例.属性访问但实例修改时通常只创建实例属性不会影响类属性而实例属性是在实例方法内通过self.属性定义的每个实例独立拥有自己的副本修改实例属性不会影响其他实例或类属性。简单区分类属性属于“类蓝图”实例属性属于“每个具体对象”。实例属性每个对象独有的如上例中的self.name。类属性属于类本身所有对象共享的。class LLM: # 类属性记录所有已知模型的计数 total_models_created 0 def __init__(self, name): self.name name LLM.total_models_created 1 # 每次创建对象加 1 print(LLM.total_models_created) # 0 gpt LLM(gpt-4) claude LLM(claude-3) print(LLM.total_models_created) # 28.4 封装把内部细节藏起来封装是指把对象的内部状态属性和实现细节隐藏起来只通过公开的方法与外界交互。Python通过命名约定来实现“私有”单下划线_name表示“受保护的”外部不应直接访问但依然可以。双下划线__name名称修饰外部不能直接访问。class APIClient: def __init__(self, api_key): self.__api_key api_key # 私有属性 self._base_url https://api.openai.com # 受保护 def call(self, prompt): # 内部使用 __api_key 发起请求 return f使用密钥 {self.__api_key[:5]}... 调用成功回复{prompt} client APIClient(sk-123456) print(client.call(Hello)) # print(client.__api_key) # AttributeError print(client._base_url) # 可以访问但约定不要这样做封装的好处你可以随时改变内部实现如更换 API 提供商只要公开方法签名不变调用方代码完全不需要修改。8.5 继承基于通用模型创建专用模型继承允许你定义一个子类它自动拥有父类的所有属性和方法并可以增加或重写覆盖一些功能。8.5.1 基本继承class BaseLLM: def __init__(self, name, context_length): self.name name self.context_length context_length def generate(self, prompt): return f{self.name} 生成: {prompt} # 子类支持函数调用的模型 class FunctionCallingLLM(BaseLLM): def call_function(self, func_name, args): return f{self.name} 正在调用函数 {func_name}参数 {args} gpt4 FunctionCallingLLM(gpt-4, 8192) print(gpt4.generate(Hello)) # 继承的方法 print(gpt4.call_function(get_weather, {city: Beijing})) # 子类新方法8.5.2 重写方法改变父类的行为class GPT4(BaseLLM): def generate(self, prompt): # 调用父类方法并补充内容 base_response super().generate(prompt) return base_response [额外使用高精度计算] model GPT4(gpt-4, 8192) print(model.generate(讲个笑话)) # 输出gpt-4 生成: 讲个笑话 [额外使用高精度计算]8.5.3 多继承了解即可Python 支持一个子类继承多个父类但容易复杂。AI 框架中较少见。class Streamable: def stream(self): return 流式输出 class Cacheable: def cache(self): return 缓存命中 class AdvancedLLM(BaseLLM, Streamable, Cacheable): pass adv AdvancedLLM(claude, 100000) print(adv.stream())8.6 多态不同的对象相同的方法名多态允许不同类的对象对同一个方法名做出不同的响应。在 AI 中你可以定义一个统一的generate接口然后不同模型类各自实现它。class OpenAIModel: def generate(self, prompt): return OpenAI 回复: prompt class AnthropicModel: def generate(self, prompt): return Anthropic 回复: prompt def chat(model, prompt): print(model.generate(prompt)) gpt OpenAIModel() claude AnthropicModel() chat(gpt, 你好) # OpenAI 回复: 你好 chat(claude, 你好) # Anthropic 回复: 你好8.7 特殊方法魔术方法让对象更像“原生”数据在Python中有一类以双下划线开头和结尾的方法比如init、str、len它们被称为“魔术方法”。魔术方法不是让你直接调用的而是 Python 在特定场景下自动调用的。通过实现这些方法你可以让自己的类实例表现得像 Python 内置的列表、字符串、数字一样支持len()、str()、等操作。零基础理解可以把魔术方法理解为“潜规则”或“约定”。比如当Python看到len(x)时它会自动去调用x的len方法。你只要在类里写好了len方法Python 就知道你的对象也能问“有多长”。常用魔术方法举例init初始化方法。当你创建对象时比如p Person()Python 自动调用它用来设置对象的初始属性。str字符串表示。当你使用print(对象)或str(对象)时Python 自动调用它返回一个“给人看”的友好字符串。repr开发时用的字符串表示。在交互环境中直接输入对象名时显示通常返回一个可以用来重建对象的表达式。len长度。当你调用len(对象)时Python自动调用它返回一个整数。add加法。当你使用对象1 对象2时Python自动调用左边对象的add方法把右边的对象传进去。8.7.1__str__和__repr__定义对象的字符串表示class LLM: def __init__(self, name, context): self.name name self.context context def __str__(self): return fLLM({self.name}, ctx{self.context}) model LLM(gpt-4, 8192) print(model) # LLM(gpt-4, ctx8192)8.7.2__len__让len()可用class ConversationHistory: def __init__(self): self.messages [] def add(self, msg): self.messages.append(msg) def __len__(self): return len(self.messages) hist ConversationHistory() hist.add(hello) hist.add(world) print(len(hist)) # 28.7.3__call__让对象像函数一样被调用class TemperatureScaler: def __init__(self, factor1.2): self.factor factor def __call__(self, temperature): return temperature * self.factor scale TemperatureScaler(1.5) print(scale(0.7)) # 1.05对象名后面加括号就像函数调用这在 AI 框架中常用于配置某些可调用的参数变换。8.8 综合实战构建一个可扩展的 LLM 客户端系统我们将用面向对象的方法设计一个支持多厂商、带缓存、带计费的模型客户端。import hashlib import time # ---------- 1. 基础模型接口抽象基类但不严格要求---------- class BaseLLM: def __init__(self, name, price_per_1k): self.name name self.price_per_1k price_per_1k self.total_cost 0.0 def generate(self, prompt, **kwargs): 子类必须实现具体调用逻辑 raise NotImplementedError def _record_cost(self, input_tokens, output_tokens): cost (input_tokens output_tokens) / 1000 * self.price_per_1k self.total_cost cost return cost # ---------- 2. 具体模型实现 ---------- class OpenAIClient(BaseLLM): def __init__(self, api_key, model_namegpt-3.5-turbo): super().__init__(model_name, price_per_1k0.002) self.api_key api_key def generate(self, prompt, temperature0.7): # 模拟 API 调用实际会用 requests 库 print(f[OpenAI] 调用 {self.name}temperature{temperature}) # 模拟 token 计数 input_tokens len(prompt) // 4 output_text fOpenAI 回复{prompt} output_tokens len(output_text) // 4 cost self._record_cost(input_tokens, output_tokens) return { text: output_text, input_tokens: input_tokens, output_tokens: output_tokens, cost: cost } class AnthropicClient(BaseLLM): def __init__(self, api_key, model_nameclaude-3): super().__init__(model_name, price_per_1k0.025) self.api_key api_key def generate(self, prompt, temperature0.7): print(f[Anthropic] 调用 {self.name}temperature{temperature}) input_tokens len(prompt) // 4 output_text fClaude 回复{prompt} output_tokens len(output_text) // 4 cost self._record_cost(input_tokens, output_tokens) return { text: output_text, input_tokens: input_tokens, output_tokens: output_tokens, cost: cost } # ---------- 3. 带缓存的装饰器模式简化 ---------- class CachedLLM: def __init__(self, llm_client): self.llm llm_client self.cache {} def generate(self, prompt, **kwargs): key hashlib.md5(f{prompt}_{kwargs}.encode()).hexdigest() if key in self.cache: print(缓存命中) return self.cache[key] else: result self.llm.generate(prompt, **kwargs) self.cache[key] result return result # ---------- 4. 使用 ---------- if __name__ __main__: # 创建原始客户端 openai OpenAIClient(api_keysk-xxx, model_namegpt-4) # 增加缓存功能 cached_openai CachedLLM(openai) # 第一次调用 res1 cached_openai.generate(讲个笑话, temperature0.8) print(res1[text]) print(f花费: ${res1[cost]:.4f}) # 第二次调用相同 prompt会命中缓存 res2 cached_openai.generate(讲个笑话, temperature0.8) print(res2[text]) print(f总成本: {openai.total_cost})运行上述代码输出如下内容tianpengDESKTOP-4L1UF5S:~/my-ai-service$ poetry run python src/my_ai_service/loop.py [OpenAI] 调用 gpt-4temperature0.8 OpenAI 回复讲个笑话 花费: $0.0000 缓存命中 OpenAI 回复讲个笑话 总成本: 8e-06 tianpengDESKT8.9 本章小结概念含义AI 示例类 class设计蓝图class LLM:对象 instance根据类创建的具体实例gpt4 LLM(gpt-4)属性 attribute对象的数据self.name,self.context_length方法 method对象的行为def generate(self, prompt):__init__构造函数初始化对象设置 API 密钥、默认温度封装隐藏内部细节私有属性__api_key继承子类复用父类代码class FunctionCallingLLM(BaseLLM):多态不同对象相同方法名不同行为model.generate(prompt)对不同模型调不同的实现魔术方法让对象支持Python内置操作__str__,__len__,__call__