
1、空则return 0clean [] if not clean: return 0 #表示如果clean是空则返回0。 和逻辑有效一样1是True, 0是False 正常clean是0肯定是不往return 0的逻辑走那让not clean就会往return 0的逻辑走2、python的私有方法_ 前缀是 Python 的命名约定表示这是一个私有方法private method。 简单说 _count_tokens 前面的 _ 告诉使用者这是内部用的外部别直接调我我可能随时会变 没有 _ 的方法如 trim是公共接口鼓励外部调用 trimmer SlideWindowTrimmer() trimmer.trim(messages) # 正常用公共方法 trimmer._count_tokens(messages) # 也能跑但不推荐——它是内部实现细节Python 有三种下划线约定含义不同 1. 单下划线前缀 _name — 约定私有软私有-绝大多数情况下常用 纯君子协定实际外部仍可调用 最常见表示内部实现别依赖 2. 双下划线前缀 __name — 名称重整硬私有很少用 Python 会把它重命名成 _ClassName__name外部直接调用会报错 主要用于避免子类继承时方法名冲突 3. 单下划线后缀 name_ — 避免关键字冲突 跟私有无关只是当变量名和关键字撞了加个后缀绕开 class_、type_、return_ 这种 4. 双下划线前后包裹 __name__ — Python 魔术方法内置方法不用手动调python自动调 __init__、__str__、__len__ 等 这是 Python 官方保留的特殊方法不是私有约定3、深拷贝、浅拷贝4、生成器表达式sys_count sum(1 for m in messages if m[role] system) 等价于下面 sys_count 0 for m in messages: if m[role] system: sys_count 1这是一个带条件的生成器表达式遍历 messages 列表中的每一条消息 m对满足条件 m[role] system 的消息产出数字 1不满足条件的消息直接跳过不产出任何东西效果每遇到一条 role 为 system 的消息就产生一个 1。5、列表推导式其实也是生成器生成了列表而已[{role: m[role], content: m[content]} for m in messages if m.get(content)] [ 生成的新字典 for m in messages if 过滤条件 ] └──── 元素表达式 ────┘└─ 遍历 ─┘└─ 过滤 ─┘1. for m in messages —— 遍历 逐条取出 messages 列表里的消息字典 m。 2. if m.get(content) —— 过滤条件 m.get(content) 用 .get() 取 content 键的值键不存在时返回 None不会报 KeyError 这里有两种情况会被过滤掉 content 键不存在返回 None content 的值是空字符串 、None、0、False、[]、{} 等假值 只有 content 有实际内容时这条消息才会被保留 3. {role: m[role], content: m[content]} —— 元素表达式 对保留下来的每条消息新建一个字典只取 role 和 content 两个字段。 这样可以丢弃原消息中可能存在的其他字段比如 name、tool_calls、function_call 等 同时让 role 字段必须存在用 m[role] 直接取键不存在会报错6、切片[:-8]是 从头到倒数第8条之前[-8:]是 倒数第8条到最后7、zip函数#zip() 是 Python 内置函数作用就是把多个可迭代对象【按位置】配对打包成元组。 像拉链一样把两排齿一个个咬合在一起。 a [1, 2, 3] b [x, y, z] list(zip(a, b)) # → [(1, x), (2, y), (3, z)]1、#以短的为准 — 配对到最短的那个结束多出来的丢弃 list(zip([1, 2, 3], [a, b])) # → [(1, a), (2, b)] # 3 没有配对丢弃 2、可以同时配对多个 list(zip([1, 2], [a, b], [10, 20])) # → [(1, a, 10), (2, b, 20)]8、点积点积Dot Product就是两个向量对应位置相乘再求和结果是一个标量单个数字。 例如 a [1, 2, 3] b [4, 5, 6] 点积 1×4 2×5 3×6 4 10 18 32几何意义衡量两个向量的方向一致性 点积 0 → 两向量方向相近夹角 90°--锐角 点积 0 → 两向量垂直夹角 90°无关--直角 点积 0 → 两向量方向相反夹角 90°--钝角9、向量余弦相似度点积 / 向量模长的乘积点积 a [1, 2, 3] b [4, 5, 6] 点积 1×4 2×5 3×6 4 10 18 32模长 |a| √(1² 2² 3²) √(149) √14 ≈ 3.742 |b| √(4² 5² 6²) √(162536) √77 ≈ 8.775余弦相似度 cos 32 / (3.742 × 8.775) 32 / 32.835 ≈ 0.974610、向量数据库中的向量向量的维度取决于你用的 embedding 模型同一个库里必须维度一致。存入和检索必须用同一个模型否则维度对不上一条向量大概如下{ id: msg_001, vector: [0.051, -0.005, ..., 0.028], // 1024个浮点数 metadata: {text: 我想申请房贷, role: user} } id向量Id vector语义坐标 metadata元数据工程优化索引加速能在百万级数据里毫秒返回11、函数引用 VS 函数调用query_order vs query_order() query_order → 函数对象的引用可以存储、传递 query_order() → 调用函数得到返回值12、LLM响应内容解析OpenAI SDK 响应解析的标准链式取值resp.json()[choices][0][message][content].strip() resp.json() # ① 把HTTP响应体(JSON字符串)解析成Python字典 [choices] # ② 取出choices列表 —— 模型生成的候选结果数组 [0] # ③ 取第一个候选通常只生成1个 [message] # ④ 取该候选的message对象 [content] # ⑤ 取message里的content字段 —— 即模型输出的文本正文 .strip() # ⑥ 去除首尾空白字符(空格/换行)API原始返回{choices: [{message: {role: assistant,content: {\intent\: \loan_apply\, ...} },finish_reason: stop} ]}{ choices: [ { message: { role: assistant, content: {\intent\: \loan_apply\, ...} }, finish_reason: stop } ] }13、pydanticPydantic 是 Python 最流行的数据验证库核心作用用 Python 类型注解定义数据结构自动帮你做类型校验 解析 序列化。14、请求LLM的调用方式裸 requests resp requests.post( BASE_URL, headers{api-key: API_KEY, Content-Type: application/json}, json{model: MODEL, messages: messages, temperature: 0}, timeout30, ) return resp.json()[choices][0][message][content].strip()OpenAI SDK 就是 OpenAI 官方发布的编程语言客户端库封装好的工具包让你不用手写 HTTP 请求就能调用大模型 API。很多大模型平台都兼容了 OpenAI 的接口标准——请求格式、响应格式一模一样OpenAI SDK client OpenAI(api_keyAPI_KEY, base_urlBASE_URL) resp client.chat.completions.create( modelMODEL, messagesmessages, temperature0 ) return resp.choices[0].message.content15、json.loads()json.loads()就是把一个JSON 格式的字符串转成Python 对象通常是 dict。loads里的s代表string字符串。import json # 模型返回的原始文本字符串{} reply {thought: 需要查订单, action: query_order, args: {order_id: PRE202601001}} # 转成 Python 字典{key1:value1,key2:value2} data json.loads(reply) # 现在可以用 key 取值了 print(data[action]) # → query_order print(data[args][order_id]) # → PRE202601001