diff --git a/.github/workflows/jan-electron-build-nightly.yml b/.github/workflows/jan-electron-build-nightly.yml index 1a34fee4d..d0c2adb0c 100644 --- a/.github/workflows/jan-electron-build-nightly.yml +++ b/.github/workflows/jan-electron-build-nightly.yml @@ -1,4 +1,4 @@ -name: Jan Build Electron App Nightly +name: Jan Build Electron App Nightly or Manual on: schedule: @@ -173,8 +173,9 @@ jobs: name: jan-linux-amd64-${{ steps.version_update.outputs.new_version }}.deb path: ./electron/dist/*.deb - noti-discord: + noti-discord-nightly: needs: [build-macos, build-windows-x64, build-linux-x64] + if: github.event_name == 'schedule' runs-on: ubuntu-latest steps: - name: Notify Discord @@ -183,3 +184,15 @@ jobs: args: "Nightly build artifact: https://github.com/janhq/jan/actions/runs/{{ GITHUB_RUN_ID }}" env: DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }} + + noti-discord-manual: + needs: [build-macos, build-windows-x64, build-linux-x64] + if: github.event_name == 'workflow_dispatch' + runs-on: ubuntu-latest + steps: + - name: Notify Discord + uses: Ilshidur/action-discord@master + with: + args: "Manual build artifact: https://github.com/janhq/jan/actions/runs/{{ GITHUB_RUN_ID }}" + env: + DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }} diff --git a/README.md b/README.md index 7a1daacdd..9c686c4c2 100644 --- a/README.md +++ b/README.md @@ -55,23 +55,17 @@ As Jan is development mode, you might get stuck on a broken build. To reset your installation: -1. Delete Jan from your `/Applications` folder +1. **Remove Jan from your Applications folder and Cache folder** -1. Delete Application data: - ```sh - # Newer versions - rm -rf /Users/$(whoami)/Library/Application\ Support/jan - - # Versions 0.2.0 and older - rm -rf /Users/$(whoami)/Library/Application\ Support/jan-electron - ``` - -1. Clear Application cache: - ```sh - rm -rf /Users/$(whoami)/Library/Caches/jan* + ```bash + make clean ``` -1. Use the following commands to remove any dangling backend processes: + This will remove all build artifacts and cached files: + - Delete Jan from your `/Applications` folder + - Clear Application cache in `/Users/$(whoami)/Library/Caches/jan` + +2. Use the following commands to remove any dangling backend processes: ```sh ps aux | grep nitro @@ -124,6 +118,22 @@ make build This will build the app MacOS m1/m2 for production (with code signing already done) and put the result in `dist` folder. +## Nightly Build + +Nightly build is a process where the software is built automatically every night. This helps in detecting and fixing bugs early in the development cycle. The process for this project is defined in [`.github/workflows/jan-electron-build-nightly.yml`](.github/workflows/jan-electron-build-nightly.yml) + +You can join our Discord server [here](https://discord.gg/FTk2MvZwJH) and go to channel [github-jan](https://discordapp.com/channels/1107178041848909847/1148534730359308298) to monitor the build process. + +The nightly build is triggered at 2:00 AM UTC every day. + +The nightly build can be downloaded from the url notified in the Discord channel. Please access the url from the browser and download the build artifacts from there. + +## Manual Build + +Manual build is a process where the software is built manually by the developers. This is usually done when a new feature is implemented or a bug is fixed. The process for this project is defined in [`.github/workflows/jan-electron-build-nightly.yml`](.github/workflows/jan-electron-build-nightly.yml) + +It is similar to the nightly build process, except that it is triggered manually by the developers. + ## Acknowledgements Jan builds on top of other open-source projects: diff --git a/core/src/types/index.ts b/core/src/types/index.ts index bbd1e98de..dcbc20ca3 100644 --- a/core/src/types/index.ts +++ b/core/src/types/index.ts @@ -143,6 +143,7 @@ export type ThreadAssistantInfo = { assistant_id: string; assistant_name: string; model: ModelInfo; + instructions?: string; }; /** @@ -182,6 +183,11 @@ export interface Model { */ version: number; + /** + * The format of the model. + */ + format: string; + /** * The model download source. It can be an external url or a local filepath. */ @@ -234,6 +240,7 @@ export type ModelMetadata = { author: string; tags: string[]; size: number; + cover?: string; }; /** @@ -288,13 +295,13 @@ export type Assistant = { /** Represents the name of the object. */ name: string; /** Represents the description of the object. */ - description: string; + description?: string; /** Represents the model of the object. */ model: string; /** Represents the instructions for the object. */ - instructions: string; + instructions?: string; /** Represents the tools associated with the object. */ - tools: any; + tools?: any; /** Represents the file identifiers associated with the object. */ file_ids: string[]; /** Represents the metadata of the object. */ diff --git a/docs/docs/specs/engineering/engine.md b/docs/docs/specs/engineering/engine.md new file mode 100644 index 000000000..d25fdfc04 --- /dev/null +++ b/docs/docs/specs/engineering/engine.md @@ -0,0 +1,60 @@ +--- +title: Engine +slug: /specs/engine +--- + +:::caution + +Currently Under Development + +::: + +## Overview + +In the Jan application, engines serve as primary entities with the following capabilities: + +- Engine will be installed through `inference-extensions`. +- Models will depend on engines to do [inference](https://en.wikipedia.org/wiki/Inference_engine). +- Engine configuration and required metadata will be stored in a json file. + +## Folder Structure + +- Default parameters for engines are stored in JSON files located in the `/engines` folder. +- These parameter files are named uniquely with `engine_id`. +- Engines are referenced directly using `engine_id` in the `model.json` file. + +```yaml +jan/ + engines/ + nitro.json + openai.json + ..... +``` + +## Engine Default Parameter Files + +- Each inference engine requires default parameters to function in cases where user-provided parameters are absent. +- These parameters are stored in JSON files, structured as simple key-value pairs. + +### Example + +Here is an example of an engine file for `engine_id` `nitro`: + +```js +{ + "ctx_len": 512, + "ngl": 100, + "embedding": false, + "n_parallel": 1, + "cont_batching": false + "prompt_template": "<|im_start|>system\n{system_message}<|im_end|>\n<|im_start|>user\n{prompt}<|im_end|>\n<|im_start|>assistant" +} +``` + +For detailed engine parameters, refer to: [Nitro's Model Settings](https://nitro.jan.ai/features/load-unload#table-of-parameters) + +## Adding an Engine + +- Engine parameter files are automatically generated upon installing an `inference-extension` in the Jan application. + +--- diff --git a/docs/docs/specs/engineering/models.md b/docs/docs/specs/engineering/models.md index decf8f5e9..e10fbd088 100644 --- a/docs/docs/specs/engineering/models.md +++ b/docs/docs/specs/engineering/models.md @@ -53,9 +53,9 @@ jan/ # Jan root folder Here's a standard example `model.json` for a GGUF model. -- `source_url`: https://huggingface.co/TheBloke/zephyr-7B-beta-GGUF/. ```js +{ "id": "zephyr-7b", // Defaults to foldername "object": "model", // Defaults to "model" "source_url": "https://huggingface.co/TheBloke/zephyr-7B-beta-GGUF/blob/main/zephyr-7b-beta.Q4_K_M.gguf", @@ -64,15 +64,16 @@ Here's a standard example `model.json` for a GGUF model. "version": "1", // Defaults to 1 "created": 1231231, // Defaults to file creation time "description": null, // Defaults to null -"state": enum[null, "downloading", "ready", "starting", "stopping", ...] +"state": enum[null, "ready"] "format": "ggufv3", // Defaults to "ggufv3" -"settings": { // Models are initialized with settings - "ctx_len": 2048, +"engine": "nitro", // engine_id specified in jan/engine folder +"engine_parameters": { // Engine parameters inside model.json can override + "ctx_len": 2048, // the value inside the base engine.json "ngl": 100, "embedding": true, "n_parallel": 4, }, -"parameters": { // Models are called parameters +"model_parameters": { // Models are called parameters "stream": true, "max_tokens": 2048, "stop": [""], // This usually can be left blank, only used with specific need from model author @@ -85,9 +86,10 @@ Here's a standard example `model.json` for a GGUF model. "assets": [ // Defaults to current dir "file://.../zephyr-7b-q4_k_m.bin", ] +} ``` -The model settings in the example can be found at: [Nitro's model settings](https://nitro.jan.ai/features/load-unload#table-of-parameters) +The engine parameters in the example can be found at: [Nitro's model settings](https://nitro.jan.ai/features/load-unload#table-of-parameters) The model parameters in the example can be found at: [Nitro's model parameters](https://nitro.jan.ai/api-reference#tag/Chat-Completion) diff --git a/docs/docusaurus.config.js b/docs/docusaurus.config.js index da62e3399..47a7910a0 100644 --- a/docs/docusaurus.config.js +++ b/docs/docusaurus.config.js @@ -3,7 +3,6 @@ require("dotenv").config(); -const lightCodeTheme = require("prism-react-renderer/themes/github"); const darkCodeTheme = require("prism-react-renderer/themes/dracula"); /** @type {import('@docusaurus/types').Config} */ @@ -115,11 +114,11 @@ const config = { primaryColor: "#1a73e8", primaryColorDark: "#1a73e8", options: { - requiredPropsFirst: true, - noAutoAuth: true, - hideDownloadButton: true, - disableSearch: true, - }, + requiredPropsFirst: true, + noAutoAuth: true, + hideDownloadButton: true, + disableSearch: true, + }, }, }, ], @@ -135,48 +134,72 @@ const config = { docs: { sidebar: { hideable: true, - autoCollapseCategories: true, + autoCollapseCategories: false, }, }, - // SEO Docusarus + // SEO Docusarus metadata: [ - { name: 'description', content: 'Jan is a ChatGPT-alternative that runs on your own computer, with a local API server.' }, - { name: 'keywords', content: 'Jan, ChatGPT alternative, on-premises AI, local API server, local AI, llm, conversational AI, no-subscription fee' }, - { name: 'robots', content: 'index, follow' }, - { property: 'og:title', content: 'Run your own AI | Jan' }, - { property: 'og:description', content: 'Jan is a ChatGPT-alternative that runs on your own computer, with a local API server.' }, - { property: 'og:image', content: 'https://jan.ai/img/jan-social-card.png' }, - { property: 'og:type', content: 'website' }, - { property: 'twitter:card', content: 'summary_large_image' }, - { property: 'twitter:site', content: '@janhq_' }, - { property: 'twitter:title', content: 'Run your own AI | Jan' }, - { property: 'twitter:description', content: 'Jan is a ChatGPT-alternative that runs on your own computer, with a local API server.' }, - { property: 'twitter:image', content: 'https://jan.ai/img/jan-social-card.png' }, + { + name: "description", + content: + "Jan is a ChatGPT-alternative that runs on your own computer, with a local API server.", + }, + { + name: "keywords", + content: + "Jan, ChatGPT alternative, on-premises AI, local API server, local AI, llm, conversational AI, no-subscription fee", + }, + { name: "robots", content: "index, follow" }, + { property: "og:title", content: "Run your own AI | Jan" }, + { + property: "og:description", + content: + "Jan is a ChatGPT-alternative that runs on your own computer, with a local API server.", + }, + { + property: "og:image", + content: "https://jan.ai/img/jan-social-card.png", + }, + { property: "og:type", content: "website" }, + { property: "twitter:card", content: "summary_large_image" }, + { property: "twitter:site", content: "@janhq_" }, + { property: "twitter:title", content: "Run your own AI | Jan" }, + { + property: "twitter:description", + content: + "Jan is a ChatGPT-alternative that runs on your own computer, with a local API server.", + }, + { + property: "twitter:image", + content: "https://jan.ai/img/jan-social-card.png", + }, ], headTags: [ // Declare a preconnect tag { - tagName: 'link', + tagName: "link", attributes: { - rel: 'preconnect', - href: 'https://jan.ai/', + rel: "preconnect", + href: "https://jan.ai/", }, }, // Declare some json-ld structured data { - tagName: 'script', + tagName: "script", attributes: { - type: 'application/ld+json', + type: "application/ld+json", }, innerHTML: JSON.stringify({ - '@context': 'https://schema.org/', - '@type': 'localAI', - name: 'Jan', - description: "Jan is a ChatGPT-alternative that runs on your own computer, with a local API server.", - keywords: "Jan, ChatGPT alternative, on-premises AI, local API server, local AI, llm, conversational AI, no-subscription fee", + "@context": "https://schema.org/", + "@type": "localAI", + name: "Jan", + description: + "Jan is a ChatGPT-alternative that runs on your own computer, with a local API server.", + keywords: + "Jan, ChatGPT alternative, on-premises AI, local API server, local AI, llm, conversational AI, no-subscription fee", applicationCategory: "BusinessApplication", operatingSystem: "Multiple", - url: 'https://jan.ai/', + url: "https://jan.ai/", }), }, ], @@ -234,10 +257,10 @@ const config = { prism: { theme: darkCodeTheme, darkTheme: darkCodeTheme, - additionalLanguages: ["python"], + additionalLanguages: ["python", "powershell", "bash"], }, colorMode: { - defaultMode: "dark", + defaultMode: "light", disableSwitch: false, respectPrefersColorScheme: false, }, diff --git a/docs/sidebars.js b/docs/sidebars.js index edef458cd..384f47e9d 100644 --- a/docs/sidebars.js +++ b/docs/sidebars.js @@ -81,6 +81,7 @@ const sidebars = { items: [ "specs/engineering/chats", "specs/engineering/models", + "specs/engineering/engine", "specs/engineering/threads", "specs/engineering/messages", "specs/engineering/assistants", diff --git a/docs/src/components/Announcement/index.js b/docs/src/containers/Banner/index.js similarity index 96% rename from docs/src/components/Announcement/index.js rename to docs/src/containers/Banner/index.js index 922be62f7..33061de0f 100644 --- a/docs/src/components/Announcement/index.js +++ b/docs/src/containers/Banner/index.js @@ -27,7 +27,7 @@ export default function AnnoncementBanner() { return (
-
+
{ + const url = `https://api.github.com/repos/${repoOwner}/${repoName}/releases/latest`; + try { + const response = await axios.get(url); + return response.data; + } catch (error) { + console.error(error); + return null; + } + }; + + const extractAppName = (fileName) => { + // Extract appname using a regex that matches the provided file formats + const regex = /^(.*?)-(?:mac|win|linux)-(?:arm64|x64|amd64)-.*$/; + const match = fileName.match(regex); + return match ? match[1] : null; + }; + + useEffect(() => { + const updateDownloadLinks = async () => { + try { + const releaseInfo = await getLatestReleaseInfo("janhq", "jan"); + + // Extract appname from the first asset name + const firstAssetName = releaseInfo.assets[0].name; + const appname = extractAppName(firstAssetName); + + if (!appname) { + console.error( + "Failed to extract appname from file name:", + firstAssetName + ); + + return; + } + + // Remove 'v' at the start of the tag_name + const tag = releaseInfo.tag_name.startsWith("v") + ? releaseInfo.tag_name.substring(1) + : releaseInfo.tag_name; + + const updatedSystems = systems.map((system) => { + const downloadUrl = system.fileFormat + .replace("{appname}", appname) + .replace("{tag}", tag); + return { + ...system, + href: `https://github.com/janhq/jan/releases/download/${releaseInfo.tag_name}/${downloadUrl}`, + }; + }); + + setSystems(updatedSystems); + } catch (error) { + console.error("Failed to update download links:", error); + } + }; + + updateDownloadLinks(); + }, []); + + return ( + + ); +} diff --git a/docs/src/components/Elements/downloadLink.js b/docs/src/containers/Elements/downloadLink.js similarity index 100% rename from docs/src/components/Elements/downloadLink.js rename to docs/src/containers/Elements/downloadLink.js diff --git a/docs/src/components/Elements/dropdown.js b/docs/src/containers/Elements/dropdown.js similarity index 100% rename from docs/src/components/Elements/dropdown.js rename to docs/src/containers/Elements/dropdown.js diff --git a/docs/src/components/Footer/index.js b/docs/src/containers/Footer/index.js similarity index 61% rename from docs/src/components/Footer/index.js rename to docs/src/containers/Footer/index.js index e5c09fe8e..d2fde6b8a 100644 --- a/docs/src/components/Footer/index.js +++ b/docs/src/containers/Footer/index.js @@ -1,19 +1,37 @@ import React from "react"; +import { AiOutlineGithub, AiOutlineTwitter } from "react-icons/ai"; +import { BiLogoDiscordAlt } from "react-icons/bi"; + +const socials = [ + { + icon: , + href: "https://twitter.com/janhq_", + }, + { + icon: , + href: "https://discord.com/invite/FTk2MvZwJH", + }, + { + icon: , + href: "https://github.com/janhq/jan", + }, +]; + const menus = [ { name: "For Developers", child: [ { - menu: "Documentation (WIP)", + menu: "Documentation", path: "/intro", }, { - menu: "Hardware (WIP)", + menu: "Hardware", path: "/hardware", }, { - menu: "API Reference (WIP)", + menu: "API Reference", path: "/api-reference", }, { @@ -67,16 +85,32 @@ const getCurrentYear = new Date().getFullYear(); export default function Footer() { return ( -