用前端技术栈中的D3.js、JavaScript及SVG图形处理,并结合大模型接口,用户可通过聊天窗口与大模型进行交互,实现对图形的操作与更新。
可以选择任何一家平台的大模型API接口。此处推荐大家一个平台,https://platform.deepseek.com/usage,该平台可以调用deepseek大模型,新用户注册有免费500tokens的额度。
调用方法如下:(调用方法有多种,可以参考官方文档首次调用 API | DeepSeek API Docs,下面给我我在项目中的调用方法)
const apiKey = "apiKey";
const response = await fetch('<https://api.deepseek.com/chat/completions>', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${apiKey}`
},
body: JSON.stringify({
model: 'deepseek-chat',
messages: [{ role: "user", content: prompt }],
temperature: 0.3,
max_tokens: 1000
})
});
const data = await response.json();
let modifiedSVGCode = data.message.content;
大模型的返回结果往往为大量文本和代码的集合,我们通过简单的调用得到的只是大模型的全部应答,若要实现对图形的操作,需要对大模型的返回结果进行清洗,例如实验中需要实现对图形进行变换操作,我们只需要将选中图形的SVG代码传给大模型,通过获取大模型回复的代码输出对原有画布中的图形进行操作。
提供一种操作逻辑流程:通过解析大模型返回的SVG代码,在原有画布中将原有模型SVG代码进行替换即可做到利用大模型进行操作的效果。
下面为对大模型返回代码进行操作的示例:
// 提取SVG代码(如果返回的是代码块格式)
if (content.includes('```')) {
modifiedSVGCode = content.split('```')[1]
.replace(/^xml\\n|^svg\\n/i, '')
.trim();
}
// 验证SVG代码
if (!modifiedSVGCode.includes('<') || !modifiedSVGCode.includes('>')) {
throw new Error('返回的内容不包含有效的SVG代码');
}
// 更新画布中的图形
const parser = new DOMParser();
const doc = parser.parseFromString(modifiedSVGCode, "image/svg+xml");
const newElement = doc.documentElement;
// 保存原始的变换信息和属性
const originalTransform = selectedShape.attr("transform");
const originalScale = selectedShape.attr("data-scale");
const originalType = selectedShape.attr("data-type");
const originalId = selectedShape.attr("data-id");
// 保存原有图形的引用和数据
const oldElements = selectedShape.selectAll("*:not(.resize-area)").nodes();
const oldResizeArea = selectedShape.select(".resize-area");
const oldResizeAreaData = oldResizeArea.empty() ? null : {
x: oldResizeArea.attr("x"),
y: oldResizeArea.attr("y"),
width: oldResizeArea.attr("width"),
height: oldResizeArea.attr("height")
};
// 创建新的组来存放过渡元素
const transitionGroup = selectedShape.append("g")
.attr("class", "transition-group")
.style("opacity", 1);
// 将原有元素克隆到过渡组
oldElements.forEach(node => {
transitionGroup.node().appendChild(node.cloneNode(true));
});
// 清除原有内容(但保留过渡组)
selectedShape.selectAll("*:not(.transition-group)").remove();
// 添加新的图形元素
Array.from(newElement.children).forEach(child => {
if (child.tagName !== 'defs') {
selectedShape.node().appendChild(child.cloneNode(true));
}
});