From 3c294d6a48f8da86511189f845e614ec28fd6363 Mon Sep 17 00:00:00 2001 From: Hoang Ha <64120343+hahuyhoang411@users.noreply.github.com> Date: Wed, 24 Apr 2024 14:17:42 +0700 Subject: [PATCH 1/3] Chore: Add phi-3 (#2794) * add: phi-3 * chore: bump version * fix: correct model id --- .../inference-nitro-extension/package.json | 2 +- .../resources/models/phi3-3.8b/model.json | 32 +++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 extensions/inference-nitro-extension/resources/models/phi3-3.8b/model.json diff --git a/extensions/inference-nitro-extension/package.json b/extensions/inference-nitro-extension/package.json index dabda9aec..9a98eed8c 100644 --- a/extensions/inference-nitro-extension/package.json +++ b/extensions/inference-nitro-extension/package.json @@ -1,7 +1,7 @@ { "name": "@janhq/inference-nitro-extension", "productName": "Nitro Inference Engine", - "version": "1.0.2", + "version": "1.0.3", "description": "This extension embeds Nitro, a lightweight (3mb) inference engine written in C++. See https://nitro.jan.ai.\nAdditional dependencies could be installed to run without Cuda Toolkit installation.", "main": "dist/index.js", "node": "dist/node/index.cjs.js", diff --git a/extensions/inference-nitro-extension/resources/models/phi3-3.8b/model.json b/extensions/inference-nitro-extension/resources/models/phi3-3.8b/model.json new file mode 100644 index 000000000..0d789385b --- /dev/null +++ b/extensions/inference-nitro-extension/resources/models/phi3-3.8b/model.json @@ -0,0 +1,32 @@ +{ + "sources": [ + { + "url": "https://huggingface.co/microsoft/Phi-3-mini-4k-instruct-gguf/resolve/main/Phi-3-mini-4k-instruct-q4.gguf", + "filename": "Phi-3-mini-4k-instruct-q4.gguf" + } + ], + "id": "phi3-3.8b", + "object": "model", + "name": "Phi-3 Mini", + "version": "1.0", + "description": "Phi-3 Mini is Microsoft's newest, compact model designed for mobile use.", + "format": "gguf", + "settings": { + "ctx_len": 4096, + "prompt_template": "<|system|>\n{system_message}<|end|>\n<|user|>\n{prompt}<|end|>\n<|assistant|>\n", + "llama_model_path": "Phi-3-mini-4k-instruct-q4.gguf" + }, + "parameters": { + "max_tokens": 4096, + "stop": ["<|end|>"] + }, + "metadata": { + "author": "Microsoft", + "tags": [ + "3B", + "Finetuned" + ], + "size": 2320000000 + }, + "engine": "nitro" + } From 96abd533c418c277465178253ff4e4e6d2a8896c Mon Sep 17 00:00:00 2001 From: Inchoker <54902491+Inchoker@users.noreply.github.com> Date: Wed, 24 Apr 2024 18:16:57 +0700 Subject: [PATCH 2/3] feat: cohere remote API extension (#2785) * fix core * add cohere extension * add cohere response customizable * nitpicking * use transformResponse * Update extensions/inference-cohere-extension/src/index.ts Co-authored-by: Louis * use prettier * Update extensions/inference-cohere-extension/src/index.ts Co-authored-by: Louis * pass requestBody as object * transformPayload as a property * This is not correct. CHATBOT is an equivalent role to assistant. system message should be used with the preamble parameter and should not be included in the chat_history --------- Co-authored-by: Jack Tri Le Co-authored-by: Louis --- .../browser/extensions/engines/OAIEngine.ts | 20 +++- .../browser/extensions/engines/helpers/sse.ts | 23 ++-- core/src/types/api/index.ts | 7 ++ .../inference-cohere-extension/README.md | 79 +++++++++++++ .../inference-cohere-extension/package.json | 43 +++++++ .../resources/models.json | 26 +++++ .../resources/settings.json | 23 ++++ .../inference-cohere-extension/src/index.ts | 110 ++++++++++++++++++ .../inference-cohere-extension/tsconfig.json | 14 +++ .../webpack.config.js | 37 ++++++ 10 files changed, 368 insertions(+), 14 deletions(-) create mode 100644 extensions/inference-cohere-extension/README.md create mode 100644 extensions/inference-cohere-extension/package.json create mode 100644 extensions/inference-cohere-extension/resources/models.json create mode 100644 extensions/inference-cohere-extension/resources/settings.json create mode 100644 extensions/inference-cohere-extension/src/index.ts create mode 100644 extensions/inference-cohere-extension/tsconfig.json create mode 100644 extensions/inference-cohere-extension/webpack.config.js diff --git a/core/src/browser/extensions/engines/OAIEngine.ts b/core/src/browser/extensions/engines/OAIEngine.ts index 6340333e9..01ef55e5e 100644 --- a/core/src/browser/extensions/engines/OAIEngine.ts +++ b/core/src/browser/extensions/engines/OAIEngine.ts @@ -31,6 +31,12 @@ export abstract class OAIEngine extends AIEngine { // The loaded model instance loadedModel: Model | undefined + // Transform the payload + transformPayload?: Function + + // Transform the response + transformResponse?: Function + /** * On extension load, subscribe to events. */ @@ -78,13 +84,23 @@ export abstract class OAIEngine extends AIEngine { } const header = await this.headers() + let requestBody = { + messages: data.messages ?? [], + model: model.id, + stream: true, + ...model.parameters, + } + if (this.transformPayload) { + requestBody = this.transformPayload(requestBody) + } requestInference( this.inferenceUrl, - data.messages ?? [], + requestBody, model, this.controller, - header + header, + this.transformResponse ).subscribe({ next: (content: any) => { const messageContent: ThreadContent = { diff --git a/core/src/browser/extensions/engines/helpers/sse.ts b/core/src/browser/extensions/engines/helpers/sse.ts index dbc58501a..7ae68142f 100644 --- a/core/src/browser/extensions/engines/helpers/sse.ts +++ b/core/src/browser/extensions/engines/helpers/sse.ts @@ -7,21 +7,16 @@ import { ErrorCode, ModelRuntimeParams } from '../../../../types' */ export function requestInference( inferenceUrl: string, - recentMessages: any[], + requestBody: any, model: { id: string parameters: ModelRuntimeParams }, controller?: AbortController, - headers?: HeadersInit + headers?: HeadersInit, + transformResponse?: Function ): Observable { return new Observable((subscriber) => { - const requestBody = JSON.stringify({ - messages: recentMessages, - model: model.id, - stream: true, - ...model.parameters, - }) fetch(inferenceUrl, { method: 'POST', headers: { @@ -30,17 +25,17 @@ export function requestInference( 'Accept': model.parameters.stream ? 'text/event-stream' : 'application/json', ...headers, }, - body: requestBody, + body: JSON.stringify(requestBody), signal: controller?.signal, }) .then(async (response) => { if (!response.ok) { const data = await response.json() - let errorCode = ErrorCode.Unknown; + let errorCode = ErrorCode.Unknown if (data.error) { errorCode = data.error.code ?? data.error.type ?? ErrorCode.Unknown } else if (response.status === 401) { - errorCode = ErrorCode.InvalidApiKey; + errorCode = ErrorCode.InvalidApiKey } const error = { message: data.error?.message ?? 'Error occurred.', @@ -52,7 +47,11 @@ export function requestInference( } if (model.parameters.stream === false) { const data = await response.json() - subscriber.next(data.choices[0]?.message?.content ?? '') + if (transformResponse) { + subscriber.next(transformResponse(data)) + } else { + subscriber.next(data.choices[0]?.message?.content ?? '') + } } else { const stream = response.body const decoder = new TextDecoder('utf-8') diff --git a/core/src/types/api/index.ts b/core/src/types/api/index.ts index fb0167a04..1a95ad9c9 100644 --- a/core/src/types/api/index.ts +++ b/core/src/types/api/index.ts @@ -1,3 +1,5 @@ +import { ChatCompletionMessage } from '../inference' + /** * Native Route APIs * @description Enum of all the routes exposed by the app @@ -154,3 +156,8 @@ export const APIEvents = [ ...Object.values(DownloadEvent), ...Object.values(LocalImportModelEvent), ] +export type PayloadType = { + messages: ChatCompletionMessage[] + model: string + stream: Boolean +} diff --git a/extensions/inference-cohere-extension/README.md b/extensions/inference-cohere-extension/README.md new file mode 100644 index 000000000..089a096e8 --- /dev/null +++ b/extensions/inference-cohere-extension/README.md @@ -0,0 +1,79 @@ +# Cohere Engine Extension + +Created using Jan extension example + +# Create a Jan Extension using Typescript + +Use this template to bootstrap the creation of a TypeScript Jan extension. 🚀 + +## Create Your Own Extension + +To create your own extension, you can use this repository as a template! Just follow the below instructions: + +1. Click the Use this template button at the top of the repository +2. Select Create a new repository +3. Select an owner and name for your new repository +4. Click Create repository +5. Clone your new repository + +## Initial Setup + +After you've cloned the repository to your local machine or codespace, you'll need to perform some initial setup steps before you can develop your extension. + +> [!NOTE] +> +> You'll need to have a reasonably modern version of +> [Node.js](https://nodejs.org) handy. If you are using a version manager like +> [`nodenv`](https://github.com/nodenv/nodenv) or +> [`nvm`](https://github.com/nvm-sh/nvm), you can run `nodenv install` in the +> root of your repository to install the version specified in +> [`package.json`](./package.json). Otherwise, 20.x or later should work! + +1. :hammer_and_wrench: Install the dependencies + + ```bash + npm install + ``` + +1. :building_construction: Package the TypeScript for distribution + + ```bash + npm run bundle + ``` + +1. :white_check_mark: Check your artifact + + There will be a tgz file in your extension directory now + +## Update the Extension Metadata + +The [`package.json`](package.json) file defines metadata about your extension, such as +extension name, main entry, description and version. + +When you copy this repository, update `package.json` with the name, description for your extension. + +## Update the Extension Code + +The [`src/`](./src/) directory is the heart of your extension! This contains the +source code that will be run when your extension functions are invoked. You can replace the +contents of this directory with your own code. + +There are a few things to keep in mind when writing your extension code: + +- Most Jan Extension functions are processed asynchronously. + In `index.ts`, you will see that the extension function will return a `Promise`. + + ```typescript + import { events, MessageEvent, MessageRequest } from '@janhq/core' + + function onStart(): Promise { + return events.on(MessageEvent.OnMessageSent, (data: MessageRequest) => + this.inference(data) + ) + } + ``` + + For more information about the Jan Extension Core module, see the + [documentation](https://github.com/janhq/jan/blob/main/core/README.md). + +So, what are you waiting for? Go ahead and start customizing your extension! diff --git a/extensions/inference-cohere-extension/package.json b/extensions/inference-cohere-extension/package.json new file mode 100644 index 000000000..ea03bb33b --- /dev/null +++ b/extensions/inference-cohere-extension/package.json @@ -0,0 +1,43 @@ +{ + "name": "@janhq/inference-cohere-extension", + "productName": "Cohere Inference Engine", + "version": "1.0.0", + "description": "This extension enables Cohere chat completion API calls", + "main": "dist/index.js", + "module": "dist/module.js", + "engine": "cohere", + "author": "Jan ", + "license": "AGPL-3.0", + "scripts": { + "build": "tsc -b . && webpack --config webpack.config.js", + "build:publish": "rimraf *.tgz --glob && yarn build && npm pack && cpx *.tgz ../../pre-install", + "sync:core": "cd ../.. && yarn build:core && cd extensions && rm yarn.lock && cd inference-cohere-extension && yarn && yarn build:publish" + }, + "exports": { + ".": "./dist/index.js", + "./main": "./dist/module.js" + }, + "devDependencies": { + "cpx": "^1.5.0", + "rimraf": "^3.0.2", + "webpack": "^5.88.2", + "webpack-cli": "^5.1.4", + "ts-loader": "^9.5.0" + }, + "dependencies": { + "@janhq/core": "file:../../core", + "fetch-retry": "^5.0.6", + "ulidx": "^2.3.0" + }, + "engines": { + "node": ">=18.0.0" + }, + "files": [ + "dist/*", + "package.json", + "README.md" + ], + "bundleDependencies": [ + "fetch-retry" + ] +} diff --git a/extensions/inference-cohere-extension/resources/models.json b/extensions/inference-cohere-extension/resources/models.json new file mode 100644 index 000000000..0fce51fb7 --- /dev/null +++ b/extensions/inference-cohere-extension/resources/models.json @@ -0,0 +1,26 @@ + [ + { + "sources": [ + { + "url": "https://cohere.com" + } + ], + "id": "command-r-plus", + "object": "model", + "name": "Command R+", + "version": "1.0", + "description": "Command R+ is an instruction-following conversational model that performs language tasks at a higher quality, more reliably, and with a longer context than previous models. It is best suited for complex RAG workflows and multi-step tool use.", + "format": "api", + "settings": {}, + "parameters": { + "max_tokens": 128000, + "temperature": 0.7, + "stream": false + }, + "metadata": { + "author": "Cohere", + "tags": ["General", "Big Context Length"] + }, + "engine": "cohere" + } +] diff --git a/extensions/inference-cohere-extension/resources/settings.json b/extensions/inference-cohere-extension/resources/settings.json new file mode 100644 index 000000000..9d9fb60de --- /dev/null +++ b/extensions/inference-cohere-extension/resources/settings.json @@ -0,0 +1,23 @@ +[ + { + "key": "chat-completions-endpoint", + "title": "Chat Completions Endpoint", + "description": "The endpoint to use for chat completions. See the [Cohere API documentation](https://docs.cohere.com/reference/chat) for more information.", + "controllerType": "input", + "controllerProps": { + "placeholder": "https://api.cohere.ai/v1/chat", + "value": "https://api.cohere.ai/v1/chat" + } + }, + { + "key": "cohere-api-key", + "title": "API Key", + "description": "The Cohere API uses API keys for authentication. Visit your [API Keys](https://platform.openai.com/account/api-keys) page to retrieve the API key you'll use in your requests.", + "controllerType": "input", + "controllerProps": { + "placeholder": "sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", + "value": "", + "type": "password" + } + } +] diff --git a/extensions/inference-cohere-extension/src/index.ts b/extensions/inference-cohere-extension/src/index.ts new file mode 100644 index 000000000..b986a25eb --- /dev/null +++ b/extensions/inference-cohere-extension/src/index.ts @@ -0,0 +1,110 @@ +/** + * @file This file exports a class that implements the InferenceExtension interface from the @janhq/core package. + * The class provides methods for initializing and stopping a model, and for making inference requests. + * It also subscribes to events emitted by the @janhq/core package and handles new message requests. + * @version 1.0.0 + * @module inference-openai-extension/src/index + */ + +import { RemoteOAIEngine } from '@janhq/core' +import { PayloadType } from '@janhq/core' +import { ChatCompletionRole } from '@janhq/core' + +declare const SETTINGS: Array +declare const MODELS: Array + +enum Settings { + apiKey = 'cohere-api-key', + chatCompletionsEndPoint = 'chat-completions-endpoint', +} + +enum RoleType { + user = 'USER', + chatbot = 'CHATBOT', + system = 'SYSTEM', +} + +type CoherePayloadType = { + chat_history?: Array<{ role: RoleType; message: string }> + message?: string, + preamble?: string, +} + +/** + * A class that implements the InferenceExtension interface from the @janhq/core package. + * The class provides methods for initializing and stopping a model, and for making inference requests. + * It also subscribes to events emitted by the @janhq/core package and handles new message requests. + */ +export default class JanInferenceCohereExtension extends RemoteOAIEngine { + inferenceUrl: string = '' + provider: string = 'cohere' + + override async onLoad(): Promise { + super.onLoad() + + // Register Settings + this.registerSettings(SETTINGS) + this.registerModels(MODELS) + + this.apiKey = await this.getSetting(Settings.apiKey, '') + this.inferenceUrl = await this.getSetting( + Settings.chatCompletionsEndPoint, + '' + ) + if (this.inferenceUrl.length === 0) { + SETTINGS.forEach((setting) => { + if (setting.key === Settings.chatCompletionsEndPoint) { + this.inferenceUrl = setting.controllerProps.value as string + } + }) + } + } + + onSettingUpdate(key: string, value: T): void { + if (key === Settings.apiKey) { + this.apiKey = value as string + } else if (key === Settings.chatCompletionsEndPoint) { + if (typeof value !== 'string') return + + if (value.trim().length === 0) { + SETTINGS.forEach((setting) => { + if (setting.key === Settings.chatCompletionsEndPoint) { + this.inferenceUrl = setting.controllerProps.value as string + } + }) + } else { + this.inferenceUrl = value + } + } + } + + transformPayload = (payload: PayloadType): CoherePayloadType => { + if (payload.messages.length === 0) { + return {} + } + const convertedData:CoherePayloadType = { + chat_history: [], + message: '', + } + payload.messages.forEach((item, index) => { + // Assign the message of the last item to the `message` property + if (index === payload.messages.length - 1) { + convertedData.message = item.content as string + return + } + if (item.role === ChatCompletionRole.User) { + convertedData.chat_history.push({ role: RoleType.user, message: item.content as string}) + } else if (item.role === ChatCompletionRole.Assistant) { + convertedData.chat_history.push({ + role: RoleType.chatbot, + message: item.content as string, + }) + } else if (item.role === ChatCompletionRole.System) { + convertedData.preamble = item.content as string + } + }) + return convertedData + } + + transformResponse = (data: any) => data.text +} diff --git a/extensions/inference-cohere-extension/tsconfig.json b/extensions/inference-cohere-extension/tsconfig.json new file mode 100644 index 000000000..2477d58ce --- /dev/null +++ b/extensions/inference-cohere-extension/tsconfig.json @@ -0,0 +1,14 @@ +{ + "compilerOptions": { + "target": "es2016", + "module": "ES6", + "moduleResolution": "node", + "outDir": "./dist", + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": false, + "skipLibCheck": true, + "rootDir": "./src" + }, + "include": ["./src"] +} diff --git a/extensions/inference-cohere-extension/webpack.config.js b/extensions/inference-cohere-extension/webpack.config.js new file mode 100644 index 000000000..cd5e65c72 --- /dev/null +++ b/extensions/inference-cohere-extension/webpack.config.js @@ -0,0 +1,37 @@ +const webpack = require('webpack') +const packageJson = require('./package.json') +const settingJson = require('./resources/settings.json') +const modelsJson = require('./resources/models.json') + +module.exports = { + experiments: { outputModule: true }, + entry: './src/index.ts', // Adjust the entry point to match your project's main file + mode: 'production', + module: { + rules: [ + { + test: /\.tsx?$/, + use: 'ts-loader', + exclude: /node_modules/, + }, + ], + }, + plugins: [ + new webpack.DefinePlugin({ + MODELS: JSON.stringify(modelsJson), + SETTINGS: JSON.stringify(settingJson), + ENGINE: JSON.stringify(packageJson.engine), + }), + ], + output: { + filename: 'index.js', // Adjust the output file name as needed + library: { type: 'module' }, // Specify ESM output format + }, + resolve: { + extensions: ['.ts', '.js'], + }, + optimization: { + minimize: false, + }, + // Add loaders and other configuration as needed for your project +} From 957f4629e279ea6c6b075075a0e9b2375805b201 Mon Sep 17 00:00:00 2001 From: hiento09 <136591877+hiento09@users.noreply.github.com> Date: Thu, 25 Apr 2024 10:55:11 +0700 Subject: [PATCH 3/3] Add workflow test openai api (#2778) * Add workflow test openai api * chore: add filename as attribute to each test case * chore: correct label * feat: create pytest.ini * chore: remote extra " * chore: rename workflow to group similar type * chore: remove auto build on push to main * chore: rename job --------- Co-authored-by: Hien To Co-authored-by: Van-QA --- .github/ISSUE_TEMPLATE/bug_report.md | 7 +- .../workflows/jan-electron-build-nightly.yml | 8 +- .github/workflows/jan-electron-build.yml | 2 +- .../jan-electron-linter-and-test.yml | 2 +- .github/workflows/jan-openai-api-test.yml | 90 +++++++++++++++++++ .../workflows/jan-server-build-nightly.yml | 2 +- .github/workflows/jan-server-build.yml | 2 +- docs/openapi/version.txt | 1 + docs/tests/conftest.py | 6 ++ docs/tests/pytest.ini | 8 ++ 10 files changed, 112 insertions(+), 16 deletions(-) create mode 100644 .github/workflows/jan-openai-api-test.yml create mode 100644 docs/openapi/version.txt create mode 100644 docs/tests/conftest.py create mode 100644 docs/tests/pytest.ini diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index c081d4414..a6fa42e2d 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -25,16 +25,13 @@ If applicable, add screenshots to help explain your issue. **Environment details** - Operating System: [Specify your OS. e.g., MacOS Sonoma 14.2.1, Windows 11, Ubuntu 22, etc] -- Jan Version: [e.g., 0.4.3] +- Jan Version: [e.g., 0.4.xxx nightly or manual] - Processor: [e.g., Apple M1, Intel Core i7, AMD Ryzen 5, etc] - RAM: [e.g., 8GB, 16GB] - Any additional relevant hardware specifics: [e.g., Graphics card, SSD/HDD] **Logs** -If the cause of the error is not clear, kindly provide your usage logs: -- `tail -n 50 ~/jan/logs/app.log` if you are using the UI -- `tail -n 50 ~/jan/logs/server.log` if you are using the local api server -Making sure to redact any private information. +If the cause of the error is not clear, kindly provide your usage logs: https://jan.ai/docs/troubleshooting#how-to-get-error-logs **Additional context** Add any other context or information that could be helpful in diagnosing the problem. diff --git a/.github/workflows/jan-electron-build-nightly.yml b/.github/workflows/jan-electron-build-nightly.yml index bc32f9ccc..26bbcc672 100644 --- a/.github/workflows/jan-electron-build-nightly.yml +++ b/.github/workflows/jan-electron-build-nightly.yml @@ -1,12 +1,6 @@ -name: Jan Build Electron App Nightly or Manual +name: Electron Builder - Nightly / Manual on: - push: - branches: - - main - paths-ignore: - - 'README.md' - - 'docs/**' schedule: - cron: '0 20 * * 1,2,3' # At 8 PM UTC on Monday, Tuesday, and Wednesday which is 3 AM UTC+7 Tuesday, Wednesday, and Thursday workflow_dispatch: diff --git a/.github/workflows/jan-electron-build.yml b/.github/workflows/jan-electron-build.yml index 89e130bbd..8898c8211 100644 --- a/.github/workflows/jan-electron-build.yml +++ b/.github/workflows/jan-electron-build.yml @@ -1,4 +1,4 @@ -name: Jan Build Electron App +name: Electron Builder - Tag on: push: diff --git a/.github/workflows/jan-electron-linter-and-test.yml b/.github/workflows/jan-electron-linter-and-test.yml index 3221a63ec..f84971be9 100644 --- a/.github/workflows/jan-electron-linter-and-test.yml +++ b/.github/workflows/jan-electron-linter-and-test.yml @@ -1,4 +1,4 @@ -name: Jan Electron Linter & Test +name: Test - Linter & Playwright on: workflow_dispatch: push: diff --git a/.github/workflows/jan-openai-api-test.yml b/.github/workflows/jan-openai-api-test.yml new file mode 100644 index 000000000..9964a41d5 --- /dev/null +++ b/.github/workflows/jan-openai-api-test.yml @@ -0,0 +1,90 @@ +name: Test - OpenAI API Pytest collection +on: + workflow_dispatch: + push: + branches: + - main + - dev + - release/** + paths: + - "docs/**" + + pull_request: + branches: + - main + - dev + - release/** + paths: + - "docs/**" + +jobs: + openai-python-tests: + runs-on: [self-hosted, Linux, ubuntu-desktop] + if: (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository) || github.event_name == 'push' || github.event_name == 'workflow_dispatch' + steps: + - name: Getting the repo + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Installing node + uses: actions/setup-node@v3 + with: + node-version: 20 + + - name: "Cleanup cache" + continue-on-error: true + run: | + rm -rf ~/jan + make clean + + - name: install dependencies + run: | + npm install -g @stoplight/prism-cli + + - name: create python virtual environment and run test + run: | + python3 -m venv /tmp/jan + source /tmp/jan/bin/activate + # Clone openai-api-python repo + OPENAI_API_PYTHON_TAG=$(cat docs/openapi/version.txt) + git clone https://github.com/openai/openai-python.git + cd openai-python + git checkout $OPENAI_API_PYTHON_TAG + + python3 -m venv /tmp/jan + source /tmp/jan/bin/activate + pip install -r requirements-dev.lock + pip install pytest-reportportal pytest-html + + # Create pytest.ini file with content + cat ../docs/tests/pytest.ini >> pytest.ini + echo "rp_api_key = ${{ secrets.REPORT_PORTAL_API_KEY }}" >> pytest.ini + echo "rp_endpoint = ${{ secrets.REPORT_PORTAL_URL_PYTEST }}" >> pytest.ini + cat pytest.ini + + # Append to conftest.py + cat ../docs/tests/conftest.py >> tests/conftest.py + + # start mock server and run test then stop mock server + prism mock ../docs/openapi/jan.yaml > prism.log & prism_pid=$! && pytest --reportportal --html=report.html && kill $prism_pid + deactivate + + - name: Upload Artifact + uses: actions/upload-artifact@v2 + with: + name: report + path: | + openai-python/report.html + openai-python/assets + openai-python/prism.log + + - name: clean up + if: always() + run: | + rm -rf /tmp/jan + rm -rf openai-python + rm -rf report.html + rm -rf report.zip + + diff --git a/.github/workflows/jan-server-build-nightly.yml b/.github/workflows/jan-server-build-nightly.yml index 0d1bc3ca8..3e394be7e 100644 --- a/.github/workflows/jan-server-build-nightly.yml +++ b/.github/workflows/jan-server-build-nightly.yml @@ -1,4 +1,4 @@ -name: Jan Build Docker Nightly or Manual +name: Docker Builder - Nightly / Manual on: push: diff --git a/.github/workflows/jan-server-build.yml b/.github/workflows/jan-server-build.yml index 0665838d6..503efd298 100644 --- a/.github/workflows/jan-server-build.yml +++ b/.github/workflows/jan-server-build.yml @@ -1,4 +1,4 @@ -name: Jan Build Docker +name: Docker Builder - Tag on: push: diff --git a/docs/openapi/version.txt b/docs/openapi/version.txt new file mode 100644 index 000000000..5656be624 --- /dev/null +++ b/docs/openapi/version.txt @@ -0,0 +1 @@ +v1.23.2 \ No newline at end of file diff --git a/docs/tests/conftest.py b/docs/tests/conftest.py new file mode 100644 index 000000000..86b6c422f --- /dev/null +++ b/docs/tests/conftest.py @@ -0,0 +1,6 @@ +def pytest_collection_modifyitems(items): + for item in items: + # add the name of the file (without extension) as a marker + filename = item.nodeid.split("::")[0].split("/")[-1].replace(".py", "") + marker = pytest.mark.file(filename) + item.add_marker(marker) diff --git a/docs/tests/pytest.ini b/docs/tests/pytest.ini new file mode 100644 index 000000000..c815b335d --- /dev/null +++ b/docs/tests/pytest.ini @@ -0,0 +1,8 @@ +[pytest] +rp_project = openai-api-test +rp_launch = OpenAI Collection Test +rp_launch_description = Full collection to ensure compatibility with OpenAI API +rp_launch_attributes = 'CI' +filterwarnings = ignore::pytest.PytestUnknownMarkWarning +log_format = %(asctime)s %(levelname)s %(message)s +log_date_format = %Y-%m-%d %H:%M:%S