Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 5 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
<div align="center">
<a href="https://github.com/Phala-Network/ai-agent-template-openai">
<h1>AI Agent Contract Template with OpenAI</h1>
<img height="320" src="./public/AI-Agent-Contract.jpg" />
<br />
</a>
<a href="https://platform.openai.com/docs/api-reference">
<img height="32" src="public/powered-by-openai-badge-filled-on-light.svg" />
<br />
<img height="320" src="https://github.com/user-attachments/assets/275831c8-50dd-4cf3-b07a-9414e292e0e0" />


</a>

<p align="center">
<br><br>
Host your AI Agent Contract on Phala's decentralized serverless cloud.
<br />
<a href="https://github.com/Phala-Network/ai-agent-template-openai"><strong>Explore the docs »</strong></a>
Expand Down
11 changes: 8 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@
"node": ">=18"
},
"scripts": {
"build": "phat-fn build --experimentalAsync",
"test": "tsx tests/test.ts",
"build": "tsup --config tsup.config.ts",
"test": "vitest",
"dev": "tsx watch src/index.ts",
"set-secrets": "tsx scripts/setSecrets.ts",
"lint": "tsc --noEmit",
"publish-agent": "phat-fn build --experimentalAsync && tsx scripts/publish.ts"
Expand All @@ -21,9 +22,13 @@
"thirdweb": "^5.32.3",
"tsx": "^4.7.1",
"typescript": "^5.3.3",
"vitest": "^2.1.5",
"wyhash": "^1.0.0"
},
"dependencies": {
"openai": "^4.56.0"
"@hono/node-server": "^1.13.7",
"hono": "^4.6.11",
"openai": "^4.56.0",
"tsup": "^8.3.5"
}
}
86 changes: 0 additions & 86 deletions src/httpSupport.ts

This file was deleted.

81 changes: 59 additions & 22 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,68 @@
import { Request, Response, route } from './httpSupport'

import OpenAI from 'openai'

async function GET(req: Request): Promise<Response> {
let result = { message: '' }
const secrets = req.secret || {}
const queries = req.queries
const openaiApiKey = (secrets.openaiApiKey) ? secrets.openaiApiKey as string : ''
const openai = new OpenAI({ apiKey: openaiApiKey })
// Choose from any model listed here https://platform.openai.com/docs/models
const openAiModel = (queries.openAiModel) ? queries.openAiModel[0] : 'gpt-4o';
import { serve } from '@hono/node-server'
import { Hono } from 'hono'
import OpenAI from "openai";

export const app = new Hono()

const getAPIKey = () => {
console.log('Getting API Key from vault...')
let vault: Record<string, string> = {};
try {
vault = JSON.parse(process.env.secret || '')
} catch (e) {
console.error(e)
}
return vault.openaiApiKey || ''
}

function buildHtmlResponse(message: string) {
const htmlResponse = `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>OpenAI Response</title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; background-color: #f9f9f9; }
.container { max-width: 600px; margin: auto; padding: 20px; border: 1px solid #ccc; border-radius: 10px; background-color: #fff; box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); }
h1 { color: #28a745; }
p { font-size: 1.2em; color: #333; }
</style>
</head>
<body>
<div class="container">
<h1>Response</h1>
<p>${message}</p>
</div>
</body>
</html>
`;
return htmlResponse;
}

app.get('/', async (c) => {
let result = {message: ''}
const openaiApiKey = getAPIKey()
const queries = c.req.queries() || {}
const openai = new OpenAI({apiKey: openaiApiKey})
const openAiModel = (queries.openAiModel) ? queries.openAiModel[0] : 'gpt-3.5-turbo';
const query = (queries.chatQuery) ? queries.chatQuery[0] as string : 'Who are you?'

const completion = await openai.chat.completions.create({
messages: [{ role: "system", content: `${query}` }],
messages: [{role: "system", content: `${query}`}],
model: `${openAiModel}`,
})

result.message = (completion.choices) ? completion.choices[0].message.content as string : 'Failed to get result'

return new Response(JSON.stringify(result))
}
return c.html(buildHtmlResponse(result.message))

async function POST(req: Request): Promise<Response> {
return new Response(JSON.stringify({message: 'Not Implemented'}))
}
})

export default async function main(request: string) {
return await route({ GET, POST }, request)
}
const port = 3000
console.log(`Server is running on http://localhost:${port}`)

serve({
fetch: app.fetch,
port
})
32 changes: 32 additions & 0 deletions tests/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import {afterAll, describe, test, vi, expect, beforeAll} from 'vitest'
import { app } from '../src/'
import * as path from "node:path";

const chatQuery = 'Who are you two?';
const model = 'claude-3-5-sonnet-20241022';

// Set Testing env secrets
const secretsFile = '../secrets/default.json'
vi.stubEnv('secret', JSON.stringify(require(path.join(__dirname, secretsFile))))

describe('Test OpenAI Agent Contract', () => {
test('returns default response when no query parameters are provided', async () => {
const resp = await app.request('/')
expect(resp.status).toBe(200)
const text = await resp.text();
expect(text).toContain('<h1>Response</h1>')
}, 10000) // Define o timeout para 10 segundos

test('returns response with provided query parameters', async () => {
const resp = await app.request('/?chatQuery=Hello&openAiModel=gpt-3.5-turbo')
expect(resp.status).toBe(200)
const text = await resp.text();
expect(text).toContain('<h1>Response</h1>')

}, 10000) // Define o timeout para 10 segundos
// Define o timeout para 10 segundos
})

afterAll(async () => {
console.log(`\nNow you are ready to publish your agent, add secrets, and interact with your agent in the following steps:\n- Execute: 'npm run publish-agent'\n- Set secrets: 'npm run set-secrets'\n- Go to the url produced by setting the secrets (e.g. https://wapo-testnet.phala.network/ipfs/QmPQJD5zv3cYDRM25uGAVjLvXGNyQf9Vonz7rqkQB52Jae?key=b092532592cbd0cf)`)
}) ;