当前位置:AIGC资讯 > AIGC > 正文

不用魔法,快速、手摸手上线Midjourney!【附源码】【示例】

首先来一波感谢:
感谢laf提供赞助,目前可以免费使用Midjourney进行开发和测试。
感谢白夜、米开朗基杨@sealos.io的耐心解答,让我对laf有了更多的使用与了解。
什么是laf?来了解下。
文末有【示例】

开始

废话不多说,进入正题。
laf在做一个活动,可以使用快速上手Midjourney《人人都能接入 Midjourney》。具体活动,可以查看论坛。

原理

原理部分不涉及代码,涉及背景介绍,熟悉的同学可以略过。因为midjourney官方没有提供API功能,所以有国外大神将开源了一款模拟请求工具,来请求midjourney,laf将这代码集成到内部的npm包中。如果需要github地址,欢迎留言,我私信给您。
所以laf平台,加上下面的实例代码可以很好的快速接入到系统中。

开始

要现有个laf账号,会有免费1月的试用,本次调用mj(以下代指midjourney),所以要在laf.dev上注册使用,这是运行在新加坡环境上。

代码逻辑

我的核心思想是这样的:先要有个核心与midjourney交互的代码,上层的我们想做的业务逻辑可以自己定义。

代码

laf 是一个云开发平台,可以将代码暴露成api形式,进行调用,一些其他鉴权等,可以在之前我写的文章中找到灵感:腾讯云开发迁移实录

要做一个云函数,处理与midjourney交互,我这里起名云函数mj-send
import cloud from '@lafjs/cloud'
import { Midjourney, MidjourneyMessage } from 'midjourney'
const SERVER_ID = '' // Midjourney 服务 ID
const CHANNEL_ID = '' // Midjourney 频道 ID
const SALAI_TOKEN = '' // Midjourney 服务 Token

const Limit = 100
const MaxWait = 3

const client = new Midjourney({
  ServerId: SERVER_ID,
  ChannelId: CHANNEL_ID,
  SalaiToken: SALAI_TOKEN,
  Debug: true,
  SessionId: SALAI_TOKEN,
  Limit: Limit,
  MaxWait: MaxWait
});

export default async function (ctx: FunctionContext) {
  const { type, param } = ctx.body
  switch (type) {
    case 'RetrieveMessages':
      return await RetrieveMessages(param)
    case 'imagine':
      return await imagine(param)
    case 'upscale':
      return await upscale(param)
    case 'variation':
      return await variation(param)
  }

}

// 查询最近消息
async function RetrieveMessages(param) {
  console.log("RetrieveMessages")
  const client = new MidjourneyMessage({
    ChannelId: CHANNEL_ID,
    SalaiToken: SALAI_TOKEN,
  });
  const msg = await client.RetrieveMessages();
  console.log("RetrieveMessages success ", msg)
  return msg
}

// 创建生图任务
async function imagine(param) {
  console.log("imagine", param)
  const { question, msg_Id } = param
  const msg = await client.Imagine(
    `[${msg_Id}] ${question}`,
    (uri: string, progress: string) => {
      console.log("loading", uri, "progress", progress);
    }
  );
  console.log("imagine success ", msg)
  return true
}

// upscale 放大图片
async function upscale(param) {
  console.log("upscale", param)
  const { question, index, id, url } = param
  const hash = url.split("_").pop()?.split(".")[0] ?? ""
  console.log(hash)
  const msg = await client.Upscale(
    question,
    index,
    id,
    hash,
    (uri: string, progress: string) => {
      console.log("loading", uri, "progress", progress);
    }
  );
  console.log("upscale success ", msg)
  return msg
}

// variation 变换图片
async function variation(param) {
  console.log("variation", param)
  const client = new Midjourney({
    ServerId: SERVER_ID,
    ChannelId: CHANNEL_ID,
    SalaiToken: SALAI_TOKEN,
    Debug: true,
    SessionId: SALAI_TOKEN,
    Limit: Limit,
    MaxWait: 100
  });
  const { question, index, id, url } = param
  const hash = url.split("_").pop()?.split(".")[0] ?? ""
  const msg = await client.Variation(
    question,
    index,
    id,
    hash,
    (uri: string, progress: string) => {
      console.log("loading", uri, "progress", progress);
    }
  );
  console.log("variation success ", msg)
  return msg
}

什么?没有账号?仔细看帖,里面有获取方式
什么?已经有了midjourney付费账号,没有key?大佬我们做朋友,留言我来告诉你。
发布即可调用,怎么调用?我把curl给你,你看看结构就懂了,该替换的替换。

画图

画图需要一些时间,这里默认使用的fast,但也是会花时间的,所以成图我们要在之后调用查询接口查看。

question:就是prompt,这里要输入英文。 关注下参数msg_Id,后面有用
curl --location --request POST 'https://<你的发布地址服务>' \
--header 'User-Agent: apifox/1.0.0 (https://www.apifox.cn)' \
--header 'Content-Type: application/json' \
--data-raw '{
  "type": "imagine",
  "param": {
    "question": "a dog",
    "msg_Id": 1684585158
  }
}'
查询
curl --location --request POST 'https://<你的发布地址服务>' \
--header 'User-Agent: apifox/1.0.0 (https://www.apifox.cn)' \
--header 'Content-Type: application/json' \
--data-raw '{
  "type":"RetrieveMessages"
}'

如何获取到我刚创建的图呢?先看一下返回的结果。

[
    {
        "id": "1109565864640008202",
        "type": 0,
        "content": "**[1684582132] a dog --seed 8925 --v 5** - <@1013684342851117146> (fast)",
        "channel_id": "1109368983364313204",
        "author": {
            "id": "936929561302675456",
            "username": "Midjourney Bot",
            "global_name": null,
            "avatar": "4a79ea7cd151474ff9f6e08339d69380",
            "discriminator": "9282",
            "public_flags": 589824,
            "bot": true,
            "avatar_decoration": null
        },
        "attachments": [
            {
                "id": "1109565863994077215",
                "filename": "johnsonmaureen_1684582132_a_dog_a062b5e2-ab39-40b0-b281-1365695529d5.png",
                "size": 4275948,
                "url": "https://cdn.discordapp.com/attachments/1109368983364313204/1109565863994077215/johnsonmaureen_1684582132_a_dog_a062b5e2-ab39-40b0-b281-1365695529d5.png",
                "proxy_url": "https://media.discordapp.net/attachments/1109368983364313204/1109565863994077215/johnsonmaureen_1684582132_a_dog_a062b5e2-ab39-40b0-b281-1365695529d5.png",
                "width": 2048,
                "height": 2048,
                "content_type": "image/png"
            }
        ]
    }
    **省略其他数据**
]

返回结果为数组,还记得上面的msg_Id吗,在JSON结构中查看content部分,就可以看到
"content": "**[1684582132] a dog --seed 8925 --v 5** - <@1013684342851117146> (fast)", 所以,我们可以用这个字段来进行筛选。$.attachments[0].url就是成图了。

选取生成大图
如果再返回的四张图有一张看得不错,怎么生成大图呢?先给你个表格,告诉你哪是1,哪是3 1 2 3 4

然后来看如何传参

curl --location --request POST 'https://<你的发布地址服务>' \
--header 'User-Agent: apifox/1.0.0 (https://www.apifox.cn)' \
--header 'Content-Type: application/json' \
--data-raw '{
  "type": "upscale",
  "param": {
    "id": "1109460470152319086",
    "question":"a dog",
    "index": 3,
"url":"https://cdn.discordapp.com/attachments/1109368983364313204/1109460469628022915/johnsonmaureen_1684585158_a_dog_d5b7e35c-0fce-4f7d-b440-35f5602d2f25.png"
  }
}'

解释下参数:

id: 是查询返回结果体里的id question,是最开始输入进去的prompt index: 你想要的第几张图 url:是查询返回结果体里的url,四张图拼一起的那个。

别问我怎么知道的,我都是翻代码看得。

重绘
当看上这4张图中某一个的风格或者样式之后,可以根据这个风格重绘。
curl --location --request POST 'https://<你的发布地址服务>' \
--header 'User-Agent: apifox/1.0.0 (https://www.apifox.cn)' \
--header 'Content-Type: application/json' \
--data-raw '{
  "type": "variation",
  "param": {
    "id": "1109460470152319086",
    "question": "a dog",
    "index": 3,
    "url": "https://cdn.discordapp.com/attachments/1109368983364313204/1109460469628022915/johnsonmaureen_1684585158_a_dog_d5b7e35c-0fce-4f7d-b440-35f5602d2f25.png"
  }
}'

参数解释不说了,跟上面类似。

至此教程结束了

赶紧去上手做点什么吧,实践出真知~

作品展示

这次其实是laf在组织活动,想我这种平台级别思考大佬的人,不会去钻到某个应用当中,我来看看大家都画了什么图,所以我做了个简陋的页面,本人前端能力有限,代码实现全靠ChatGPT。
上链接:

laf比赛作品大赏

如果觉得不错打个赏吧,后面是答疑环节

问题

我怎么知道mj的图画完没有呢?
可以根据$.attachments[0].width的尺寸大小来看,如果小于2048,则没有生成完,没生成完其实应该是512。 怎么让图片结果与请求msg_Id绑定?
正如上文所说要自己实现一个逻辑去匹配结果,另外还有一个就是用好触发器,他会定时执行你的服务,这样你就可以将数据进行增量处理。

`

更新时间 2024-01-04