BigDL-LLM实践(10):Bigit实践——链端设计

Bigit是一款基于BigDl-LLM和LangChain的Web服务。结合区块链技术,其可以实现针对知识图谱的问答,实现让个人拥有自己的“专用大模型”。

1.链端设计思路

链端的主要功能为实现知识图谱的流通交易,进而实现大模型的流通交易,使个人拥有专用大模型的交易权。具体是结合IPFS实现链上存储图谱、大模型数据,铸造NFT并交易,从而实现知识图谱的流通与交易。
 

2.链端实现

2.1 聊天机器人NFT铸造

项目中,我们把聊天机器人用到的知识图谱存入IPFS的Pinata云端中,Prompt存入链中,并铸造聊天机器人NFT,具体的实现方式如下

/* eslint-disable @next/next/no-img-element */
import { useState } from 'react'
import { ethers } from 'ethers'
import { useRouter } from 'next/router'
import Web3Modal from 'web3modal'
import axios from 'axios';
import Image from 'next/image';

const apiKey = process.env.NEXT_PUBLIC_PINATA_CLOUD_API_KEY;
const apiSecret = process.env.NEXT_PUBLIC_PINATA_CLOUD_API_SECRET;

import {
  marketplaceAddress
} from '../config'

import NFTMarketplace from '../artifacts/contracts/NFTMarketplace.sol/NFTMarketplace.json'

export default function CreateItem() {
  const [fileUrl, setFileUrl] = useState(null)
  const [formInput, updateFormInput] = useState({ price: '', name: '', description: '' })
  const router = useRouter()

  async function onChange(e) {             //上传文件到IPFS,返回文件url存储在的fileurl中
    const file = e.target.files[0];
    const formData = new FormData();
    formData.append('file', file);

    try {
      const added = await axios.post('https://api.pinata.cloud/pinning/pinFileToIPFS', formData, {
        headers: {
          'Content-Type': `multipart/form-data; boundary=${formData._boundary}`,
          'pinata_api_key': apiKey,
          'pinata_secret_api_key': apiSecret
        }
      });

      const url = `https://gateway.pinata.cloud/ipfs/${added.data.IpfsHash}`
      setFileUrl(url)
    } catch (error) {
      console.log('Error uploading file: ', error)
    }
  }
  async function uploadToIPFS() {           //上传文件,返回文件的url
    const { name, description, price } = formInput
    if (!name || !description || !price || !fileUrl) return
    /* first, upload to IPFS */
    const data = JSON.stringify({
      name, description, kg: fileUrl
    });

    try {
      const added = await axios.post('https://api.pinata.cloud/pinning/pinJSONToIPFS', data, {
        headers: {
          'Content-Type': `application/json`,
          'pinata_api_key': apiKey,
          'pinata_secret_api_key': apiSecret
        }
      });

      const url = `https://gateway.pinata.cloud/ipfs/${added.data.IpfsHash}`
      /* after file is uploaded to IPFS, return the URL to use it in the transaction */
      return url
    } catch (error) {
      console.log('Error uploading file: ', error)
    }
  }

  async function listNFTForSale() {                    //创建NFT并上架出售
    const url = await uploadToIPFS()
    const web3Modal = new Web3Modal()
    const connection = await web3Modal.connect()
    const provider = new ethers.providers.Web3Provider(connection)
    const signer = provider.getSigner()

    /* next, create the item */
    const price = ethers.utils.parseUnits(formInput.price, 'ether')
    let contract = new ethers.Contract(marketplaceAddress, NFTMarketplace.abi, signer)
    let listingPrice = await contract.getListingPrice()
    listingPrice = listingPrice.toString()
    let transaction = await contract.createToken(url, price, { value: listingPrice })
    await transaction.wait()

    router.push('/')
  }

  return (
    <div className="flex justify-center">
      <div className="w-1/2 flex flex-col pb-12">
        <input
          placeholder="Asset Name"
          className="mt-8 border rounded p-4"
          onChange={e => updateFormInput({ ...formInput, name: e.target.value })}
        />
        <textarea
          placeholder="Asset Description"
          className="mt-2 border rounded p-4"
          onChange={e => updateFormInput({ ...formInput, description: e.target.value })}
        />
        <input
          placeholder="Asset Price in Eth"
          className="mt-2 border rounded p-4"
          onChange={e => updateFormInput({ ...formInput, price: e.target.value })}
        />
        <input
          type="file"
          name="Asset"
          className="my-4"
          onChange={onChange}
        />
        {
          fileUrl && (
            <Image className="rounded mt-4" width={200} height={500} src = "/kg.png" />
          )
        }
        <button onClick={listNFTForSale} className="font-bold mt-4 bg-black text-white rounded p-4 shadow-lg">
          Create 
        </button>
      </div>
    </div>
  )
}

2.2 聊天机器人NFT购买

本项目中,在购买了聊天机器人NFT后,dump文件会被下载到本地,Prompt会被写到项目的example.txt中,以便与后续后端大模型调入。具体的实现方式如下:
 

import { ethers } from 'ethers'
import { useEffect, useState } from 'react'
import axios from 'axios'
import Web3Modal from 'web3modal'
import Image from 'next/image';

import {
  marketplaceAddress
} from '../config'

import NFTMarketplace from '../artifacts/contracts/NFTMarketplace.sol/NFTMarketplace.json'

const rpcEndpointUrl = "http://127.0.0.1:8545";
//const rpcEndpointUrl = "https://rpc-mumbai.maticvigil.com";

export default function Home() {
  const [nfts, setNfts] = useState([])  //存储从智能合约中获取的NFT数据
  const [loadingState, setLoadingState] = useState('not-loaded')  //跟踪数据状态
  useEffect(() => {
    loadNFTs()
  }, [])

  async function loadNFTs() {
    const provider = new ethers.providers.JsonRpcProvider(rpcEndpointUrl);
    const contract = new ethers.Contract(marketplaceAddress, NFTMarketplace.abi, provider)
    const data = await contract.fetchMarketItems()

    const items = await Promise.all(data.map(async i => {
      const tokenUri = await contract.tokenURI(i.tokenId)
      const meta = await axios.get(`/api/proxy?url=${encodeURIComponent(tokenUri)}`);  //发送HTTP请求获取NFT的元数据
      let price = ethers.utils.formatUnits(i.price.toString(), 'ether')
      let item = {
        price,
        tokenId: i.tokenId.toNumber(),
        seller: i.seller,
        owner: i.owner,
        kg: meta.data.kg,
        name: meta.data.name,
        description: meta.data.description,
      }
      return item
    }))
    setNfts(items)
    setLoadingState('loaded')
  }

  async function downloadNFT(nft) {
    const response = await fetch(nft.kg);
    const blob = await response.blob();
    const downloadLink = document.createElement('a');
    downloadLink.href = URL.createObjectURL(blob);
    downloadLink.download = `${nft.name}.dump`;
    downloadLink.click();
  }

  async function buyNft(nft) {

    const web3Modal = new Web3Modal()
    const connection = await web3Modal.connect()
    const provider = new ethers.providers.Web3Provider(connection)
    const signer = provider.getSigner()
    const contract = new ethers.Contract(marketplaceAddress, NFTMarketplace.abi, signer)

    //交易实例
    const price = ethers.utils.parseUnits(nft.price.toString(), 'ether')
    const transaction = await contract.createMarketSale(nft.tokenId, {
      value: price
    })
    
    await downloadNFT(nft);    
    await axios.post('/api/writeFile', { description: nft.description });
    console.log('描述已写入文件!');
    
    await transaction.wait()
    loadNFTs()
  }

  if (loadingState === 'loaded' && !nfts.length) return (<h1 className="px-20 py-10 text-3xl">No items in marketplace</h1>)
  return (
    <div className="flex justify-center">
      <div className="px-4" style={{ maxWidth: '1600px' }}>
        <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4 pt-4">
          {
            nfts.map((nft, i) => (
              <div key={i} className="border shadow rounded-xl overflow-hidden">
                <Image src= "/kg.png" width={500} height={500} />
                <div className="p-4">
                  <p style={{ height: '64px' }} className="text-2xl font-semibold">{nft.name}</p>
                  <div style={{ height: '70px', overflow: 'hidden' }}>
                    <p className="text-gray-400">{nft.description}</p>
                  </div>
                </div>
                <div className="p-4 bg-black">
                  <p className="text-2xl font-bold text-white">{nft.price} ETH</p>
                  <button style={{ backgroundColor: 'rgb(101, 175, 80)', color: 'white', fontWeight: 'bold', paddingTop: '2px', paddingBottom: '2px', paddingLeft: '12px', paddingRight: '12px', borderRadius: '4px', width: '100%', marginTop: '4px' }} onClick={() => buyNft(nft)}>Buy</button>
                </div>
              </div>
            ))
          }
        </div>
      </div>
    </div>
  )
}

3.链端使用

1. 链端部分我们使用Hardhat框架进行智能合约开发,首先进入/ChatGo文件夹中,安装项目依赖

npm install

2. 依赖安装后,项目启动本地Hardhat节点

npx hardhat node

3. 在本地网络运行时,在单独的终端窗口中将合约部署到本地网络

npx hardhat run scripts/deploy.js --network localhost
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值