架构师指南:将 LLM 集成到 Python 自动化框架中
Source: Dev.to

架构要点
- 概率自动化 – 超越僵硬的规则。
- 三层集成 – 实用层 → 自愈层 → 代理层。
- 安全第一 – 在本地运行 LLM(例如 Ollama)以保障隐私。
- Python – AI 时代的胶水代码。
自动化架构师传统上依赖确定性的、基于规则的框架:如果元素存在就点击;如果断言失败就停止。
大型语言模型(LLM)让我们转向 概率自动化,在这里推理和意图驱动操作。
思维方式的转变
这并不是让 ChatGPT 写一个正则表达式,而是要 从根本上重构 你的框架,使其变得“智能”——能够理解意图、自我修复并分析复杂的失败。
什么是 LLM(在我们的世界里)?
在测试自动化中,LLM 可以视为 语义引擎。传统工具(Selenium、Playwright)只与应用的 语法(DOM、ID、XPath)交互,无法理解其含义。LLM 充当翻译层,掌握 UI 的 语义:
- 它可以检查原始 HTML 并识别“这是一个信用卡表单”或“那个不显眼的 div 很可能是提交按钮”。
- 对于架构师而言,LLM 是一种新组件——类似于数据库或消息队列——用于处理非结构化数据(日志、DOM、用户故事),并返回结构化的操作指令。
架构策略:如何集成 LLM
不要随意撒入 AI。对 Python 框架采用 三层集成方法。
第 1 层 – “智能”实用层(低风险)
在 utils 包中添加一个 LLM 服务类。该层 不执行测试,仅为测试提供支持。
- 测试数据生成 – 使用 LLM 创建上下文感知的边界案例(例如 “生成 5 条有效的德国地址,这些地址因特殊字符会导致正则表达式失败”)。
- 日志分析 – 测试失败时,将 traceback 和最近的日志行发送给本地模型(Ollama/Llama 3),在 HTML 报告中追加一段 “根本原因假设”。
第 2 层 – 自愈驱动(中风险)
为核心驱动(Selenium/Playwright)加上智能包装。
问题: UI 变更导致定位器失效(#submit → #submit‑v2)。
LLM 解决方案:
-
捕获
NoSuchElementException。 -
捕获当前 DOM(截断至模型的上下文窗口大小)。
-
将 DOM + 原始定位器发送给 LLM,提示类似:
“元素
#submit缺失。根据当前 HTML,最可能的 ‘提交’ 按钮选择器是什么?仅返回选择器。” -
使用建议的选择器重新尝试操作。
第 3 层 – 代理框架(高抱负)
利用 LangChain 或 AutoGen 等库,将线性脚本转变为 目标驱动的代理。
- 目标: “验证访客用户的结账流程”。
- 代理: 启动浏览器,观察 UI,决定调用哪个 Python 函数(
click_element、enter_text…),并循环执行直至达成目标或卡住。
Python 实现示例:“自愈”案例
下面是使用装饰器的具体第 2 层实现。假设使用 Python 3.10+、openai 客户端(或 requests 调用本地 Ollama 服务器)以及 Selenium。
import functools
from openai import OpenAI
from selenium.common.exceptions import NoSuchElementException
# Point to a local Ollama server for privacy
client = OpenAI(base_url="http://localhost:11434/v1", api_key="ollama")
def self_healing(func):
"""
Decorator that attempts to heal a failed element interaction
by asking a local LLM for a new selector.
"""
@functools.wraps(func)
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except NoSuchElementException:
print(f"Element missing in {func.__name__}. Attempting to heal...")
# Assume the first argument is `self` with a `driver` attribute
driver = args[0].driver
page_source = driver.page_source[:2000] # Truncate for token limits
prompt = f"""
I tried to find an element but failed.
The intended action was inside function: '{func.__name__}'.
Here is a snippet of the page HTML (truncated):
{page_source}
Identify the CSS selector that most likely represents the element intended by '{func.__name__}'.
Return ONLY the CSS selector string.
"""
response = client.chat.completions.create(
model="llama3", # Local model name
messages=[{"role": "user", "content": prompt}]
)
new_selector = response.choices[0].message.content.strip()
print(f"LLM suggested new selector: {new_selector}")
# Retry with the new selector (adapt function to accept it if needed)
return driver.find_element("css selector", new_selector)
return wrapper
# Example Page Object using the decorator
class LoginPage:
def __init__(self, driver):
self.driver = driver
@self_healing
def click_login(self):
# Original locator may become stale; LLM can find a replacement.
return self.driver.find_element("id", "old-login-id").click()
架构师的最佳实践
- 本地优先 – 在敏感环境下,避免将 DOM 数据发送至公共 API。通过 Ollama 或 LM Studio 在本地托管模型(Llama 3、Mistral 等)。
- 上下文为王 – 为 LLM 提供丰富的上下文:DOM 片段、测试意图、最近日志,而不仅仅是错误信息。
- 人为在环 – 切勿让 LLM 自动提交代码更改。生成 “补丁建议” 文件,由人工审查并批准。
结论
自动化架构师的角色正从 “维护框架” 转向 “训练助手”。通过 Python 将 LLM 融入,我们能够构建几乎像创建者一样理解应用的系统,降低不稳定性并实现自愈。
从小处入手——今天实现一个 日志分析器——再逐步推进到 自愈驱动,最终实现 代理框架。