A FLUX1 API provided by a third party to splice prompt words in URLs (https://api-flux1.api4gpt.com/?prompt=) was the base service for this site's free lead generation tool, which has recently been shut down, resulting in a lot fewer daily visitors to this site. This API can be read Full-blooded FLUX.1: Use FLUX Online without Local Deployment It is described at the end of the article. About how to use FLUX1 API to attract traffic, you can search this site's article about Wenxin Intelligent Body, which has been openly shared, but unfortunately many people do not realize its importance.
Back on topic, the paid FLUX1 API is really unaffordable, as I've heard before Silicon-based flow Provided a free FLUX1 API, but I can not code, recognize the English words are limited, and no free server to deploy the service, it is difficult here ......
This article is mainly to share ideas, and does not provide a complete operation process, the end of the article to provide directly available project code.
Going into thinking mode...
1. Is the free interface of the silicon-based flow stabilized...
2. What do I do if the free interface closes again...
3. How the code is written...
4. The core issue is: as a basic service, the biggest problem is that the access address is unchanged in the case of rapid switching services, without affecting the use of existing users, if paid to use the cost can be pocketed back why not?
project sth.
1. I'm going to construct a URL with the same format, but this URL is mine, choose the domain name img.kdjingpai.com
2. Simple API interface documentation input to the big model, should be able to write runnable code
3. hopefully can be deployed to cloudflare workers (I don't actually understand what workers support)
4. Excessive requirements, the original interface only supports splicing cue words, in fact, there are a number of needs have not been met
workflow
Find the free FLUX interface documentation for Silicon Mobility, and look for the interface address and KEY on your own.
The documentation was organized and pasted to Claude with a clear message to generate workers code, and the first round resulted in executable code.
In fact, here on the end, as long as the code to the workers bound to a domain name can be in the domestic normal access, just said the original interface some of the needs have not been met, so the code again on the basis of continue to optimize.
Demand 1
Allow the size of the generated image to be changed in the URL, when no image size is entered, a 512x512 image is generated by default (this is entered into the big model to get the new code)
By this point you will realize that the Claude quota may be insufficient, then the unlimited quota of Claude Mirror Station: Sonnet, Haiku, Opus full range of models for free! It's ready to go.
Demand 2
When the prompt word input Chinese, can not be normal and correctly generated images, so the prompt part of the conversion to English, at this time the need for a large model or translation interface to complete the free translation interface is too lazy to find, the generality is not strong, so I want to access a Free Large Model API Here I chose the GLM-4-Flash from Wisdom Spectrum.
Enter the GLM-4-Flash interface documentation and generate code on demand:
A new snippet has been added to the code to take care of the translation, which, unfortunately, executes properly at a single prompt, so no follow-up testing has been done:
Demand 3
The prompt words entered by the user may be too simple, and the generated image composition and elements do not look so good, just borrow the big model API of requirement 2 to optimize the prompt words entered by the user, and the function of optimizing the prompt words as a parameter can be spliced into the URL, this time, I used ChatGPT to have a conversation, and got the following code, and of course, the instruction of how to optimize the composition is provided by me separately:
Overly complex instructions, the generated image is easy to go out of shape, and the output format of the optimized cue word is not stable, so multiple rounds of optimization were conducted for the cue word of requirement 3 as a separate task alone, and the following instructions were obtained:
Demand 4
As a technical white, very unaccustomed to operating in the command line, and will not look at the error message, so I asked the big model to generate a GUI interface, code execution in any exception is also required to directly display the interface, which solves the daily debugging of the ease of use.
Experience this humble interface: https://img.kdjingpai.com/GUI/ (please don't use it in public services, spare me...)
Final product
A help is written in the code, as well as giving a graphical interface, not to improve the user experience, but as part of the code to allow the big model to be modified naturally as a context to think, to avoid errors. However, overly long code can still cause the big model to be misunderstood, which requires a trade-off.
Adding full comments and using help are good habits for the average person writing code.
Next I let Claude multiple rounds to optimize the code, got the following complete code, in fact, there is still a lot of room for optimization, such as the big model tells me that it is best to abstract variables to ensure program safety, to reduce the number of rounds of judgments, dealing with the request delay logic and other issues, I will not deal with. Please copy and paste to use directly:
Full deployment documentation is available at: https://github.com/pptt121212/freefluxapi
// Constants const IMAGE_API_URL = 'https://api.siliconflow.cn/v1/image/generations'; const IMAGE_API_KEY = ''; const PROCESS_API_URL = 'https://open.bigmodel.cn/api/paas/v4/chat/completions'; const PROCESS_API_KEY = ''; const DEFAULT_SIZE = '512x512'; const SIZE_REGEX = /^\d+x\d+$/; const NON_ASCII_REGEX = /[^\x00-\x7F]/; addEventListener('fetch', event => { event.respondWith(handleRequest(event.request)); }); async function handleRequest(request) { try { const url = new URL(request.url); // Check if the request is for the GUI page if (url.pathname === '/GUI/') { return new Response(getGuiPage(), { headers: { 'Content-Type': 'text/html' } }); } const prompt = url.searchParams.get('prompt'); // Check if the prompt is valid if (!prompt) { return new Response(getUsageInstructions(), { headers: { 'Content-Type': 'text/html' } }); } const { size, optimization } = parseRequestParams(request); const processedPrompt = await getProcessedPrompt(prompt, optimization); const imageUrl = await getImageUrl(processedPrompt, size); return await fetchAndReturnImage(imageUrl); } catch (error) { return new Response(error.message, { status: error.status || 500 }); } } function parseRequestParams(request) { const url = new URL(request.url); const size = url.searchParams.get('size') || DEFAULT_SIZE; const optimization = url.searchParams.get('optimization') === '1'; if (!SIZE_REGEX.test(size)) { throw new Error('Invalid size parameter. Use format: widthxheight'); } return { size, optimization }; } async function getProcessedPrompt(prompt, optimization) { if (!NON_ASCII_REGEX.test(prompt) && !optimization) { return prompt; } return processPrompt(prompt, optimization); } async function getImageUrl(prompt, size) { const response = await fetch(IMAGE_API_URL, { method: 'POST', headers: { 'Accept': 'application/json', 'Authorization': `Bearer ${IMAGE_API_KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ model: "black-forest-labs/FLUX.1-schnell", prompt, image_size: size }) }); if (!response.ok) { throw new Error(`API error: ${response.status}`); } const data = await response.json(); const imageUrl = data?.images?.[0]?.url; if (!imageUrl) { throw new Error('Unexpected API response format'); } return imageUrl; } async function fetchAndReturnImage(imageUrl) { const imageResponse = await fetch(imageUrl); const imageBlob = await imageResponse.blob(); return new Response(imageBlob, { headers: { 'Content-Type': imageResponse.headers.get('Content-Type') } }); } async function processPrompt(text, optimize) { const content = optimize ? ` # 优化以下图像prompt,保留prompt主要元素基础上使细节、构图更加丰富: ## 图像prompt: ${text} ## 优化要求 1. 优化后的图像prompt是一组<英文TAG标签>,每个TAG应该遵循构图的基本原则,将画风、构图、主体、动作、场景、元素、按顺序进行描述。 2. <英文TAG标签>中每个词组用逗号","分割,逗号","前后不允许有"空格"。 # 仅仅输出优化后的图像prompt,不要有其他说明: ` : `请将以下内容翻译为英文,保持原意:${text}`; const response = await fetch(PROCESS_API_URL, { method: 'POST', headers: { 'Authorization': `Bearer ${PROCESS_API_KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ model: "GLM-4-Flash", messages: [{ role: "user", content }] }) }); if (!response.ok) { throw new Error(`Translation/Optimization API error: ${response.status}`); } const data = await response.json(); return data.choices?.[0]?.message?.content?.trim() || text; } // 函数:返回使用说明的HTML内容 function getUsageInstructions() { return ` <!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>使用说明</title> </head> <body> <h1>使用说明</h1> <p>欢迎使用图像生成 API!请按照以下步骤生成您的图像:</p> <h2>1. 请求格式</h2> <p>访问 API 的 URL 格式如下:</p> <pre>https://your-worker-url/?prompt={您的提示}&size={图像尺寸}&optimization={优化选项}</pre> <h3>参数说明</h3> <ul> <li><strong>prompt</strong>: (必填) 您想要生成图像的描述文本,例如“一位女孩”。</li> <li><strong>size</strong>: (可选) 图像的尺寸,格式为 <code>宽度x高度</code>,默认为 <code>512x512</code>。例如:<code>256x256</code> 或 <code>1024x768</code>。</li> <li><strong>optimization</strong>: (可选) 是否进行优化,值为 <code>1</code> 表示进行优化,值为 <code>0</code> 或不提供该参数表示不进行优化。</li> </ul> <h2>2. 返回结果</h2> <p>访问 API 后,您将获得生成的图像。若请求成功,您将看到生成的图像。如果请求失败,您会看到错误信息。</p> <h2>3. 示例请求</h2> <p>您可以通过以下示例请求生成图像:</p> <pre>https://your-worker-url/?prompt=一位女孩&size=512x512&optimization=1</pre> <p>此请求将生成一幅描述为“一位女孩”的图像,并将其大小设置为 512x512 像素,并进行优化。</p> <h2>4. 注意事项</h2> <ul> <li>确保您的 <code>prompt</code> 参数包含有效的描述。</li> <li><code>size</code> 参数应遵循 <code>宽度x高度</code> 格式。</li> <li>如果使用优化功能,确保 <code>prompt</code> 中包含非 ASCII 字符。</li> </ul> <p>如有任何问题,请随时联系支持团队!</p> </body> </html> `; } // 添加图形化用户界面功能 function getGuiPage() { return ` <!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>图像生成 GUI</title> </head> <body> <h1>图像生成</h1> <form id="imageForm"> <label for="prompt">图像描述:</label><br> <input type="text" id="prompt" required><br><br> <label for="size">图像尺寸 (格式: 宽度x高度,默认: 512x512):</label><br> <input type="text" id="size" value="512x512" required><br><br> <label for="optimization">是否优化:</label><br> <select id="optimization"> <option value="0">不优化</option> <option value="1">优化</option> </select> <p>优化选项说明: 选择“优化”将使生成的图像具有更丰富的细节和构图。</p><br> <button type="submit">生成图像</button> </form> <h2>生成结果:</h2> <div id="result"></div> <div id="status"></div> <script> document.getElementById('imageForm').addEventListener('submit', async (event) => { event.preventDefault(); const prompt = document.getElementById('prompt').value; const size = document.getElementById('size').value; const optimization = document.getElementById('optimization').value; // 更新状态信息 document.getElementById('status').innerText = '正在处理请求...'; try { const response = await fetch(\`/\?prompt=\${encodeURIComponent(prompt)}&size=\${size}&optimization=\${optimization}\`); if (response.ok) { const blob = await response.blob(); const img = document.createElement('img'); img.src = URL.createObjectURL(blob); img.style.maxWidth = '100%'; document.getElementById('result').innerHTML = ''; document.getElementById('result').appendChild(img); document.getElementById('status').innerText = '图像生成成功!'; } else { document.getElementById('result').innerText = '生成图像失败: ' + response.statusText; document.getElementById('status').innerText = '请求失败,状态码: ' + response.status; } } catch (error) { document.getElementById('result').innerText = '生成图像过程中出现错误: ' + error.message; document.getElementById('status').innerText = '错误信息: ' + error.message; } }); </script> </body> </html> `; }
People tend to lust for...
The final git code optimizes a lot of details, especially abstracting away KEYs to be managed individually, and multi-KEY polling loads.
Then a wordpress image generation widget is generated based on the code, which you can see on the right side of the post page.
One thing I regret: I would like to keep a cache of generated images and corresponding URLs to avoid re-generating images when the user repeatedly opens or refreshes the URL. The logic of this function is complicated, so I give up for now.
To this point, a complete lack of understanding of the code of the white man is considered to write a very simple tool, please remember that the entire code generation process of logical combing is more important than the superb instructions, please step by step to sort out the logic of a reasonable iteration of the function, from the main to the second, from the small to the large.
This API is used to splice the URL of the generated image in the prompt word:Wenxin Intelligent Body Traffic Tips: Generate text, images, referral URLs to drive traffic to the website
Don't believe that people who don't know how to code can write a very complete set of projects, I doubt it myself anyway, and this drill, which is kind of the limit for a white guy, lasted 9 hours, so thanks for your patience in reading it.