AI驱动的表单自动填写(ai置入表格)
zhezhongyun 2025-04-30 21:18 57 浏览
我们都同意,填写表格是一项枯燥且耗时的任务。如果我们可以创建一个可以为我们填写表格的 AI 助手,让我们将时间投入到更有建设性的任务中,那会怎样?
AI 助手将能够通过调用以表单字段为参数的函数来填写表单。该函数将返回一个 JSON 对象,其中表单字段作为键,值作为要填写的值。
网络上有无数的表单,每个表单都有自己独特的结构和命名约定。直到最近,几乎不可能创建一个可以填写任何表格的通用助手。但随着 LLM 的出现,我们可以创建一个。
在大多数情况下,函数调用允许 LLM 与 API 交互,但绝大多数 Web 应用程序不公开 API,与它们交互的唯一方法是填写表格。
本文的受众
本文适用于想要了解大型语言模型 (LLM)(如 OpenAI 或 Anthropic)“函数调用”功能基础知识的程序员。
函数调用是 LLM 的基本功能,允许创建可以与外部世界交互的专用工具、代理或助手。本文将向你展示如何创建一个可以填写 HTML 表单的简单 AI 助手。
你将学到什么
通过为 LLM 提供函数签名的定义来启用函数调用。函数签名是函数预期输入属性的描述。
你将学习如何创建动态生成的 JSON 模式函数签名,允许 AI 助手与 HTML 表单交互。
JSON 模式是定义和验证 JSON 对象结构的强大工具。出于教育目的,将不使用任何外部库,只使用纯 JavaScript 代码。
1、原理及实现代码
表单可能彼此非常不同,但它们都是使用输入字段、文本区域、复选框、单选按钮等常见元素构建的。
我们将仅讨论脚本中最重要的部分。完整脚本可在此处找到。
首先,我们需要识别表单元素及其类型。无论元素类型如何,每个元素都应该有一个 name属性,该属性稍后将用作 JSON 对象中的键。
对于每种元素类型,我们将创建一个函数,该函数将返回定义元素的 JSON 模式片段。JSON 模式应包含元素用途的描述。
这对于 LLM 了解元素的用途或预期值非常有用。描述的文本将从元素的标签或占位符属性中收集。
每个元素的 Json 模式属性至少包含:
- name:元素的名称
- type:元素类型,通常是字符串
- description:元素描述
然后我们可以根据元素类型拥有更多附加字段。例如,对于输入元素,我们可以有最小、最大、模式和必填字段。
对于选择元素、单选或复选框元素,我们还添加了包含所有可能值的枚举字段。特定的复选框和单选元素应该以特殊方式处理,因为它们可以具有与一个名称相关的多个值选项。
const getInputSchema = (input) => {
const { name, type, min, max, pattern, required } = input;
if (!name) return null;
const schema = {
name,
type: type === 'number' ? 'number' : 'string',
description: getElementDescription(input),
};
if (min) schema.minimum = Number(min);
if (max) schema.maximum = Number(max);
if (pattern) schema.pattern = pattern;
return [formatName(name), schema, required];
};
const getSelectSchema = (select) => {
const { name, required } = select;
if (!name) return null;
return [
formatName(name),
{
name,
type: 'string',
description: getElementDescription(select),
enum: Array.from(select.options).map((option) => option.value),
},
required,
];
};
const getTextareaSchema = (textArea) => {
const { name, required } = textArea;
if (!name) return null;
return [
formatName(name),
{ name, type: 'string', description: getElementDescription(textArea) },
required,
];
};
const getCheckboxesSchema = ([name, values]) => {
const element = document.querySelector(`[name="${name}"]`);
const isArray = name.endsWith('[]');
const schema = {
name,
type: isArray ? 'array' : 'boolean',
description: getDescription(element),
};
if (isArray) {
schema.uniqueItems = true;
schema.items = { oneOf: values };
}
return [formatName(name), schema];
};
const getRadioSchema = ([name, values]) => {
const element = document.querySelector(`[name="${name}"]`);
return [
formatName(name),
{
name,
type: 'string',
description: getDescription(element),
enum: values.map((v) => v.const),
},
];
};
现在我们来到最重要的函数,它将使用所有可用的函数为每个表单生成模式。
const generateSchema = (form) => {
const inputSelectors = [
'input[type="text"]',
'input[type="email"]',
'input[type="number"]',
'input[type="password"]',
'input[type="tel"]',
'input[type="url"]',
'input[type="date"]',
'input[type="time"]',
'input[type="datetime-local"]',
'input[type="month"]',
'input[type="week"]',
'input[type="color"]',
'input[type="range"]',
'input[type="search"]',
].join(', ');
const inputs = Array.from(form.querySelectorAll(inputSelectors))
.map(getInputSchema)
.filter(Boolean);
const checkboxes = groupByName(
Array.from(form.querySelectorAll('input[type="checkbox"]'))
).map(getCheckboxesSchema);
const radios = groupByName(
Array.from(form.querySelectorAll('input[type="radio"]'))
).map(getRadioSchema);
const selects = Array.from(form.getElementsByTagName('select'))
.map(getSelectSchema)
.filter(Boolean);
const textAreas = Array.from(form.getElementsByTagName('textarea'))
.map(getTextareaSchema)
.filter(Boolean);
const schemaProps = [
...inputs,
...checkboxes,
...radios,
...selects,
...textAreas,
];
const required = schemaProps.filter(([, , r]) => r).map(([name]) => name);
return {
name: 'fillup_form',
description: 'Schema to fill form inputs',
parameters: {
type: 'object',
required,
properties: Object.fromEntries(
schemaProps.map(([name, schema]) => [name, schema])
),
},
};
};
此函数扫描表单中的所有输入元素并为每个元素创建一个架构。它按名称对复选框和单选按钮进行分组,并为每个组创建一个架构。最后,它创建一个包含所有表单元素的 JSON 架构。
在这里,我们定义了一个将调用 OpenAI chat completitions API 的函数。我们提供模型名称(在本例中为“gpt-4o”,这保证了函数调用的良好结果)和 API 密钥,同时我们将“温度”设置为 0 以获得确定性结果。
const callOpenAiAPI = async ({
api_key,
model = 'gpt-4o',
max_tokens = 3024,
tools,
messages,
}) => {
try {
const response = await fetch('https://api.openai.com/v1/chat/completions', {
method: 'POST',
headers: {
Authorization: `Bearer ${api_key}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
model,
max_tokens,
temperature: 0,
tools,
messages,
}),
});
return await response.json();
} catch (error) {
console.error('Error calling OpenAI API:', error);
throw error;
}
};
最后,我们可以向 OpenAI API 提交请求,并用响应填写表单。我们利用“工具”功能提供生成的模式。在这里,我们使用“自动”工具选择让 OpenAI 选择最适合该工作的工具。
我们将要填写在表单中的数据作为消息提供给 AI 助手,使用非常简单的提示调用 fillup_form,其中包含以下数据: \n${data}。
我们可以以类似的方式调用 Anthropic API,而不是 openAi。
const submitForm = async (submitButton, form, formId) => {
submitButton.classList.add('spinner');
const formSchema = generateSchema(form);
const data = document.getElementById(`_data_${formId}`).value;
const apiKey = document.getElementById(`_api-key_${formId}`).value;
try {
const llmResponse = await callOpenAiAPI({
api_key: apiKey,
tools: [{ type: 'function', function: formSchema }],
tool_choice: 'auto',
messages: [
{
role: 'user',
content: `call "fillup_form" with following data:\n${data}`,
},
],
});
const rawData =
llmResponse.choices[0].message?.tool_calls?.[0]?.function?.arguments ||
llmResponse.choices[0].message?.content;
const inputData = Object.entries(JSON.parse(rawData));
fillForm(formSchema.parameters.properties, inputData);
} catch (error) {
console.error('Error processing form submission:', error);
} finally {
submitButton.classList.remove('spinner');
}
};
上述函数返回来自 OpenAI API 的响应,其中对象将表单字段映射到要填写的值。然后我们调用 fillForm 函数用响应填充表单。瞧!表单已填写。
const fillForm = (formFields, inputData) => {
inputData.forEach(([name, value]) => {
try {
const fieldDef = formFields[name];
const fieldName = fieldDef.name;
const fieldElement = document.querySelector(`[name="${fieldName}"]`);
if (Array.isArray(value)) {
value.forEach((val) => {
const checkbox = document.querySelector(
`[name="${fieldName}"][value="${val}"]`
);
if (checkbox) checkbox.checked = true;
});
} else if (fieldElement.type === 'radio') {
const radio = document.querySelector(
`[name="${fieldName}"][value="${value}"]`
);
if (radio) radio.checked = true;
} else if (fieldElement) {
fieldElement.value = value;
}
} catch (error) {
console.error(`Error filling form field: ${name}`, error);
}
});
};
2、可以用它做什么?
可以通过添加更多高级功能(如处理文件上传、处理动态表单等)进一步改进此脚本。可能的进一步发展:
- 浏览器扩展将根据存储的配置文件自动填写页面上的表单。
- 可以创建 AI 代理来代表我们填写表单。
- 可以创建自动数据输入工具,该工具将根据数据库或任何其他来源的数据填写表单。
- 在需要保护隐私的情况下,使用 LLM 生成虚假数据。
- 我们可以使用一些持久层扩展脚本以存储填充的值,以便将来使用它们。
如果表单非常复杂且包含大量字段,请将表单拆分为较小的部分(字段集)并分别填写。
3、结束语
此脚本应该适用于大多数表单。但是,如果表单是动态的(某些表单元素在用户输入时会更改或激活)或使用一些高级功能(如文件上传)或以非标准或错误的方式构建,它可能无法按预期工作。在这种情况下,你可能需要调整脚本以处理这些情况。
原文链接:AI驱动的自动表单填写 - 汇智网
相关推荐
- Go语言标准库中5个被低估的强大package
-
在Go语言的世界里,开发者们往往对fmt、net/http这些“明星包”耳熟能详,却忽略了标准库里藏着的一批“宝藏工具”。它们功能强大却低调内敛,能解决并发控制、内存优化、日志管理等核心问题。今天就带...
- 作为测试人,如何优雅地查看Log日志?
-
作为一名测试工程师,测试工作中和Linux打交道的地方有很多。比如查看日志、定位Bug、修改文件、部署环境等。项目部署在Linux上,如果某个功能发生错误,就需要我们去排查出错的原因,所以熟练地掌握查...
- Java 从底层与接口实现了解String、StringBuffer、StringBuilder
-
String、StringBuffer和StringBuilder的接口实现关系:String:字符串常量,字符串长度不可变。Java中String是immutable(不可变)的。用于存放字符...
- FluentData 从入门到精通:C#.NET 数据访问最佳实践
-
简介FluentData是一个微型ORM(micro-ORM),主打「FluentAPI」风格,让开发者在保持对原生SQL完全控制的同时,享受链式调用的便捷性。它与Dapper、Massi...
- 团队协作-代码格式化工具clang-format
-
环境:clang-format:10.0.0前言统一的代码规范对于整个团队来说十分重要,通过git/svn在提交前进行统一的ClangFormat格式化,可以有效避免由于人工操作带来的代码格式问题。C...
- C# 数据操作系列 - 15 SqlSugar 增删改查详解(超长篇)
-
0.前言继上一篇,以及上上篇,我们对SqlSugar有了一个大概的认识,但是这并不完美,因为那些都是理论知识,无法描述我们工程开发中实际情况。而这一篇,将带领小伙伴们一起试着写一个能在工程中使用的模...
- Mac OS 下 Unix 使用最多的100条命令(收藏级)
-
MacOS内置基于Unix的强大终端(Terminal),对开发者、运维工程师和日常用户来说,掌握常用的Unix命令是提升效率的关键。本文整理了100条在MacOS下最常用的U...
- C语言字符串操作总结大全(超详细)
-
C语言字符串操作总结大全(超详细)1)字符串操作strcpy(p,p1)复制字符串strncpy(p,p1,n)复制指定长度字符串strcat(p,p1)附加字符串strncat...
- 经常使用到开源的MySQL,今天我们就来系统地认识一下
-
作为程序员,我们在项目中会使用到许多种类的数据库,根据业务类型、并发量和数据要求等选择不同类型的数据库,比如MySQL、Oracle、SQLServer、SQLite、MongoDB和Redis等。今...
- 电脑蓝屏代码大全_电脑蓝屏代码大全及解决方案
-
0X0000000操作完成0X0000001不正确的函数0X0000002系统找不到指定的文件0X0000003系统找不到指定的路径0X0000004系统无法打开文件0X0000005拒绝...
- 8个增强PHP程序安全的函数_php性能优化及安全策略
-
安全是编程非常重要的一个方面。在任何一种编程语言中,都提供了许多的函数或者模块来确保程序的安全性。在现代网站应用中,经常要获取来自世界各地用户的输入,但是,我们都知道“永远不能相信那些用户输入的数据”...
- css优化都有哪些优化方案_css性能优化技巧
-
CSS优化其实可以分成几个层面:性能优化、可维护性优化、兼容性优化以及用户体验优化。这里我帮你梳理一份比较系统的CSS优化方案清单,方便你参考:一、加载性能优化减少CSS文件体积压缩CSS...
- 筹划20年,他终于拍成了这部电影_筹划20年,他终于拍成了这部电影英语
-
如果提名好莱坞最难搞影星,你第一时间会联想到谁?是坏脾气的西恩·潘,还是曾因吸毒锒铛入狱的小罗伯特·唐尼,亦或是沉迷酒精影响工作的罗素·克劳?上述大咖,往往都有着这样或那样的瑕疵。可即便如此,却都仍旧...
- Keycloak Servlet Filter Adapter使用
-
KeycloakClientAdapters简介Keycloakclientadaptersarelibrariesthatmakeitveryeasytosecurea...
- 一些常用的linux常用的命令_linux常用命令有哪些?
-
在Linux的世界里,命令是与系统交互的基础。掌握常用命令不仅能让你高效地管理文件、进程和网络,还能为你进一步学习系统管理和自动化打下坚实的基础。本文将深入探讨一些最常用且功能强大的Linux...
- 一周热门
- 最近发表
- 标签列表
-
- HTML 教程 (33)
- HTML 简介 (35)
- HTML 实例/测验 (32)
- HTML 测验 (32)
- JavaScript 和 HTML DOM 参考手册 (32)
- HTML 拓展阅读 (30)
- HTML文本框样式 (31)
- HTML滚动条样式 (34)
- HTML5 浏览器支持 (33)
- HTML5 新元素 (33)
- HTML5 WebSocket (30)
- HTML5 代码规范 (32)
- HTML5 标签 (717)
- HTML5 标签 (已废弃) (75)
- HTML5电子书 (32)
- HTML5开发工具 (34)
- HTML5小游戏源码 (34)
- HTML5模板下载 (30)
- HTTP 状态消息 (33)
- HTTP 方法:GET 对比 POST (33)
- 键盘快捷键 (35)
- 标签 (226)
- HTML button formtarget 属性 (30)
- opacity 属性 (32)
- transition 属性 (33)