diff --git a/vector-api/package.json b/vector-api/package.json index 21fd5b8..8fdd788 100644 --- a/vector-api/package.json +++ b/vector-api/package.json @@ -21,6 +21,7 @@ "wrangler": "^3.50.0" }, "dependencies": { + "@hono/zod-validator": "^0.2.1", "@types/body-parser": "^1.19.5", "@upstash/vector": "^1.0.7", "body-parser": "^1.20.2", @@ -29,6 +30,7 @@ "hono": "^4.2.4", "langchain": "^0.1.34", "openai": "^4.35.0", - "ts-node": "^10.9.2" + "ts-node": "^10.9.2", + "zod": "^3.23.7" } } diff --git a/vector-api/pnpm-lock.yaml b/vector-api/pnpm-lock.yaml index 4f9bc7d..8337f6f 100644 --- a/vector-api/pnpm-lock.yaml +++ b/vector-api/pnpm-lock.yaml @@ -1,6 +1,13 @@ lockfileVersion: '6.0' +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + dependencies: + '@hono/zod-validator': + specifier: ^0.2.1 + version: 0.2.1(hono@4.2.4)(zod@3.23.7) '@types/body-parser': specifier: ^1.19.5 version: 1.19.5 @@ -28,6 +35,9 @@ dependencies: ts-node: specifier: ^10.9.2 version: 10.9.2(@types/node@20.12.7)(typescript@5.4.5) + zod: + specifier: ^3.23.7 + version: 3.23.7 devDependencies: '@types/cors': @@ -555,6 +565,16 @@ packages: engines: {node: '>=14'} dev: true + /@hono/zod-validator@0.2.1(hono@4.2.4)(zod@3.23.7): + resolution: {integrity: sha512-HFoxln7Q6JsE64qz2WBS28SD33UB2alp3aRKmcWnNLDzEL1BLsWfbdX6e1HIiUprHYTIXf5y7ax8eYidKUwyaA==} + peerDependencies: + hono: '>=3.9.0' + zod: ^3.19.1 + dependencies: + hono: 4.2.4 + zod: 3.23.7 + dev: false + /@jridgewell/resolve-uri@3.1.2: resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} engines: {node: '>=6.0.0'} @@ -854,8 +874,8 @@ packages: flat: 5.0.2 langsmith: 0.1.18 uuid: 9.0.1 - zod: 3.22.4 - zod-to-json-schema: 3.22.5(zod@3.22.4) + zod: 3.23.7 + zod-to-json-schema: 3.22.5(zod@3.23.7) transitivePeerDependencies: - encoding dev: false @@ -874,8 +894,8 @@ packages: p-queue: 6.6.2 p-retry: 4.6.2 uuid: 9.0.1 - zod: 3.22.4 - zod-to-json-schema: 3.22.5(zod@3.22.4) + zod: 3.23.7 + zod-to-json-schema: 3.22.5(zod@3.23.7) dev: false /@langchain/openai@0.0.28: @@ -885,8 +905,8 @@ packages: '@langchain/core': 0.1.58 js-tiktoken: 1.0.11 openai: 4.35.0 - zod: 3.22.4 - zod-to-json-schema: 3.22.5(zod@3.22.4) + zod: 3.23.7 + zod-to-json-schema: 3.22.5(zod@3.23.7) transitivePeerDependencies: - encoding dev: false @@ -1797,8 +1817,8 @@ packages: p-retry: 4.6.2 uuid: 9.0.1 yaml: 2.4.1 - zod: 3.22.4 - zod-to-json-schema: 3.22.5(zod@3.22.4) + zod: 3.23.7 + zod-to-json-schema: 3.22.5(zod@3.23.7) transitivePeerDependencies: - '@aws-crypto/sha256-js' - '@aws-sdk/client-bedrock-agent-runtime' @@ -1947,7 +1967,7 @@ packages: workerd: 1.20240405.0 ws: 8.16.0 youch: 3.3.3 - zod: 3.22.4 + zod: 3.23.7 transitivePeerDependencies: - bufferutil - supports-color @@ -2601,13 +2621,13 @@ packages: stacktracey: 2.1.8 dev: true - /zod-to-json-schema@3.22.5(zod@3.22.4): + /zod-to-json-schema@3.22.5(zod@3.23.7): resolution: {integrity: sha512-+akaPo6a0zpVCCseDed504KBJUQpEW5QZw7RMneNmKw+fGaML1Z9tUNLnHHAC8x6dzVRO1eB2oEMyZRnuBZg7Q==} peerDependencies: zod: ^3.22.4 dependencies: - zod: 3.22.4 + zod: 3.23.7 dev: false - /zod@3.22.4: - resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==} + /zod@3.23.7: + resolution: {integrity: sha512-NBeIoqbtOiUMomACV/y+V3Qfs9+Okr18vR5c/5pHClPpufWOrsx8TENboDPe265lFdfewX2yBtNTLPvnmCxwog==} diff --git a/vector-api/src/index.ts b/vector-api/src/index.ts index 9f92e85..46e7b79 100644 --- a/vector-api/src/index.ts +++ b/vector-api/src/index.ts @@ -3,6 +3,8 @@ import { Hono } from 'hono' import { env } from 'hono/adapter' import { cors } from 'hono/cors' import { RecursiveCharacterTextSplitter } from 'langchain/text_splitter' +import { zValidator } from '@hono/zod-validator'; +import { z } from 'zod' const semanticSplitter = new RecursiveCharacterTextSplitter({ chunkSize: 25, @@ -24,11 +26,11 @@ const app = new Hono() app.use(cors()) -app.post('/', async (c) => { - if (c.req.header('Content-Type') !== 'application/json') { - return c.json({ error: 'JSON body expected.' }, { status: 406 }) - } +const zodSchema = z.object({ + message: z.string().min(1, { message: "Message argument is required." }) +}) +app.post('/', zValidator('json', zodSchema), async (c) => { try { const { VECTOR_TOKEN, VECTOR_URL } = env(c) @@ -38,12 +40,7 @@ app.post('/', async (c) => { cache: false, // disable needed for cf worker deployment }) - const body = await c.req.json() - let { message } = body as { message: string } - - if (!message) { - return c.json({ error: 'Message argument is required.' }, { status: 400 }) - } + let { message } = c.req.valid('json'); // this is because of the cloudflare worker sub-request limit if (message.split(/\s/).length > 35 || message.length > 1000) {