From 0309d74ccd1f2e1fae1c8491823d904f1b64ea53 Mon Sep 17 00:00:00 2001 From: avb-is-me <104213687+avb-is-me@users.noreply.github.com> Date: Tue, 27 Feb 2024 22:38:22 +0000 Subject: [PATCH 1/9] adds code snippets for threads --- docs/openapi/jan.yaml | 193 +++++++++++++++++++++++++++++++----------- 1 file changed, 144 insertions(+), 49 deletions(-) diff --git a/docs/openapi/jan.yaml b/docs/openapi/jan.yaml index 864c80fdf..ed80faf4f 100644 --- a/docs/openapi/jan.yaml +++ b/docs/openapi/jan.yaml @@ -1,11 +1,11 @@ ---- openapi: 3.0.0 info: title: API Reference description: > # Introduction - Jan API is compatible with the [OpenAI API](https://platform.openai.com/docs/api-reference). + Jan API is compatible with the [OpenAI + API](https://platform.openai.com/docs/api-reference). version: 0.1.8 contact: name: Jan Discord @@ -20,12 +20,12 @@ tags: description: List and describe the various models available in the API. - name: Chat description: > - Given a list of messages comprising a conversation, the model will - return a response. + Given a list of messages comprising a conversation, the model will return + a response. - name: Messages description: > - Messages capture a conversation's content. This can include the - content from LLM responses and other metadata from [chat + Messages capture a conversation's content. This can include the content + from LLM responses and other metadata from [chat completions](/specs/chats). - name: Threads - name: Assistants @@ -49,16 +49,16 @@ paths: summary: | Create chat completion description: > - Creates a model response for the given chat conversation. - Equivalent to OpenAI's create chat completion. + Creates a model response for the given chat conversation. Equivalent + to OpenAI's create chat completion. requestBody: content: application/json: schema: $ref: specs/chat.yaml#/components/schemas/ChatCompletionRequest responses: - "200": + '200': description: OK content: application/json: @@ -100,12 +100,12 @@ paths: - Models summary: List models description: > - Lists the currently available models, and provides basic - information about each one such as the owner and availability. - Equivalent to OpenAI's list model. + Lists the currently available models, and provides basic information + about each one such as the owner and availability. Equivalent + to OpenAI's list model. responses: - "200": + '200': description: OK content: application/json: @@ -117,7 +117,7 @@ paths: curl -X 'GET' \ 'http://localhost:1337/v1/models' \ -H 'accept: application/json' - "/models/download/{model_id}": + /models/download/{model_id}: get: operationId: downloadModel tags: @@ -135,7 +135,7 @@ paths: description: | The ID of the model to use for this request. responses: - "200": + '200': description: OK content: application/json: @@ -147,15 +147,15 @@ paths: curl -X 'GET' \ 'http://localhost:1337/v1/models/download/{model_id}' \ -H 'accept: application/json' - "/models/{model_id}": + /models/{model_id}: get: operationId: retrieveModel tags: - Models summary: Retrieve model description: > - Get a model instance, providing basic information about the model - such as the owner and permissioning. Equivalent to OpenAI's retrieve model. parameters: @@ -168,7 +168,7 @@ paths: description: | The ID of the model to use for this request. responses: - "200": + '200': description: OK content: application/json: @@ -199,7 +199,7 @@ paths: description: | The model id to delete responses: - "200": + '200': description: OK content: application/json: @@ -228,7 +228,7 @@ paths: schema: $ref: specs/threads.yaml#/components/schemas/CreateThreadObject responses: - "200": + '200': description: Thread created successfully content: application/json: @@ -237,8 +237,8 @@ paths: x-codeSamples: - lang: cURL source: | - curl -X POST http://localhost:1337/v1/threads \ - -H "Content-Type: application/json" \ + curl -X POST http://localhost:1337/v1/threads \ + -H "Content-Type: application/json" \ -d '{ "messages": [{ "role": "user", @@ -249,6 +249,73 @@ paths: "content": "How does AI work? Explain it in simple terms." }] }' + - lang: JavaScript + source: |- + const fetch = require('node-fetch'); + + fetch('http://localhost:1337/v1/threads', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + messages: [ + { + role: 'user', + content: 'Hello, what is AI?', + file_ids: ['file-abc123'] + }, + { + role: 'user', + content: 'How does AI work? Explain it in simple terms.' + } + ] + }) + }); + - lang: Node.js + source: |- + const fetch = require('node-fetch'); + + fetch('http://localhost:1337/v1/threads', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + messages: [ + { + role: 'user', + content: 'Hello, what is AI?', + file_ids: ['file-abc123'] + }, + { + role: 'user', + content: 'How does AI work? Explain it in simple terms.' + } + ] + }) + }); + - lang: Python + source: |- + import requests + + url = 'http://localhost:1337/v1/threads' + payload = { + 'messages': [ + { + 'role': 'user', + 'content': 'Hello, what is AI?', + 'file_ids': ['file-abc123'] + }, + { + 'role': 'user', + 'content': 'How does AI work? Explain it in simple terms.' + } + ] + } + + response = requests.post(url, json=payload) + print(response.text) get: operationId: listThreads tags: @@ -257,7 +324,7 @@ paths: description: | Retrieves a list of all threads available in the system. responses: - "200": + '200': description: List of threads retrieved successfully content: application/json: @@ -282,10 +349,37 @@ paths: metadata: {} x-codeSamples: - lang: cURL - source: | - curl http://localhost:1337/v1/threads \ - -H "Content-Type: application/json" \ - "/threads/{thread_id}": + source: |- + curl http://localhost:1337/v1/threads \ + -H "Content-Type: application/json" + - lang: JavaScript + source: |- + const fetch = require('node-fetch'); + + fetch('http://localhost:1337/v1/threads', { + method: 'GET', + headers: {'Content-Type': 'application/json'} + }).then(res => res.json()) + .then(json => console.log(json)); + - lang: Node.js + source: |- + const fetch = require('node-fetch'); + + fetch('http://localhost:1337/v1/threads', { + method: 'GET', + headers: {'Content-Type': 'application/json'} + }).then(res => res.json()) + .then(json => console.log(json)); + - lang: Python + source: |- + import requests + + url = 'http://localhost:1337/v1/threads' + headers = {'Content-Type': 'application/json'} + + response = requests.get(url, headers=headers) + print(response.json()) + /threads/{thread_id}: get: operationId: getThread tags: @@ -305,7 +399,7 @@ paths: description: | The ID of the thread to retrieve. responses: - "200": + '200': description: Thread details retrieved successfully content: application/json: @@ -345,7 +439,7 @@ paths: items: $ref: specs/threads.yaml#/components/schemas/ThreadMessageObject responses: - "200": + '200': description: Thread modified successfully content: application/json: @@ -384,7 +478,7 @@ paths: description: | The ID of the thread to be deleted. responses: - "200": + '200': description: Thread deleted successfully content: application/json: @@ -405,7 +499,7 @@ paths: "https://platform.openai.com/docs/api-reference/assistants/listAssistants"> Equivalent to OpenAI's list assistants. responses: - "200": + '200': description: List of assistants retrieved successfully content: application/json: @@ -445,7 +539,7 @@ paths: source: | curl http://localhost:1337/v1/assistants \ -H "Content-Type: application/json" \ - "/assistants/{assistant_id}": + /assistants/{assistant_id}: get: operationId: getAssistant tags: @@ -465,18 +559,19 @@ paths: description: | The ID of the assistant to retrieve. responses: - "200": + '200': description: null content: application/json: schema: - $ref: specs/assistants.yaml#/components/schemas/RetrieveAssistantResponse + $ref: >- + specs/assistants.yaml#/components/schemas/RetrieveAssistantResponse x-codeSamples: - lang: cURL source: | curl http://localhost:1337/v1/assistants/{assistant_id} \ -H "Content-Type: application/json" \ - "/threads/{thread_id}/messages": + /threads/{thread_id}/messages: get: operationId: listMessages tags: @@ -495,7 +590,7 @@ paths: description: | The ID of the thread from which to retrieve messages. responses: - "200": + '200': description: List of messages retrieved successfully content: application/json: @@ -547,7 +642,7 @@ paths: - role - content responses: - "200": + '200': description: Message created successfully content: application/json: @@ -562,7 +657,7 @@ paths: "role": "user", "content": "How does AI work? Explain it in simple terms." }' - "/threads/{thread_id}/messages/{message_id}": + /threads/{thread_id}/messages/{message_id}: get: operationId: retrieveMessage tags: @@ -589,7 +684,7 @@ paths: description: | The ID of the message to retrieve. responses: - "200": + '200': description: OK content: application/json: @@ -598,8 +693,8 @@ paths: x-codeSamples: - lang: cURL source: > - curl http://localhost:1337/v1/threads/{thread_id}/messages/{message_id} - \ + curl + http://localhost:1337/v1/threads/{thread_id}/messages/{message_id} \ -H "Content-Type: application/json" x-webhooks: ModelObject: @@ -621,10 +716,9 @@ x-webhooks: post: summary: The assistant object description: > - Build assistants that can call models and use tools to perform - tasks. Equivalent - to OpenAI's assistants object. + Build assistants that can call models and use tools to perform tasks. + + Equivalent to OpenAI's assistants object. operationId: AssistantObjects tags: - Assistants @@ -651,7 +745,8 @@ x-webhooks: ThreadObject: post: summary: The thread object - description: Represents a thread that contains messages. - + Represents a thread that contains messages. Equivalent to OpenAI's thread object. operationId: ThreadObject From 08c4540f6ad5610228f2eec31aec2ecfeb7e8c2f Mon Sep 17 00:00:00 2001 From: avb-is-me <104213687+avb-is-me@users.noreply.github.com> Date: Wed, 28 Feb 2024 16:23:18 +0000 Subject: [PATCH 2/9] adds updates to assistant --- docs/openapi/jan.yaml | 119 ++++++++++++++++++++++++++---------------- 1 file changed, 73 insertions(+), 46 deletions(-) diff --git a/docs/openapi/jan.yaml b/docs/openapi/jan.yaml index 864c80fdf..76906acf3 100644 --- a/docs/openapi/jan.yaml +++ b/docs/openapi/jan.yaml @@ -1,11 +1,11 @@ ---- openapi: 3.0.0 info: title: API Reference description: > # Introduction - Jan API is compatible with the [OpenAI API](https://platform.openai.com/docs/api-reference). + Jan API is compatible with the [OpenAI + API](https://platform.openai.com/docs/api-reference). version: 0.1.8 contact: name: Jan Discord @@ -20,12 +20,12 @@ tags: description: List and describe the various models available in the API. - name: Chat description: > - Given a list of messages comprising a conversation, the model will - return a response. + Given a list of messages comprising a conversation, the model will return + a response. - name: Messages description: > - Messages capture a conversation's content. This can include the - content from LLM responses and other metadata from [chat + Messages capture a conversation's content. This can include the content + from LLM responses and other metadata from [chat completions](/specs/chats). - name: Threads - name: Assistants @@ -49,16 +49,16 @@ paths: summary: | Create chat completion description: > - Creates a model response for the given chat conversation. - Equivalent to OpenAI's create chat completion. + Creates a model response for the given chat conversation. Equivalent + to OpenAI's create chat completion. requestBody: content: application/json: schema: $ref: specs/chat.yaml#/components/schemas/ChatCompletionRequest responses: - "200": + '200': description: OK content: application/json: @@ -100,12 +100,12 @@ paths: - Models summary: List models description: > - Lists the currently available models, and provides basic - information about each one such as the owner and availability. - Equivalent to OpenAI's list model. + Lists the currently available models, and provides basic information + about each one such as the owner and availability. Equivalent + to OpenAI's list model. responses: - "200": + '200': description: OK content: application/json: @@ -117,7 +117,7 @@ paths: curl -X 'GET' \ 'http://localhost:1337/v1/models' \ -H 'accept: application/json' - "/models/download/{model_id}": + /models/download/{model_id}: get: operationId: downloadModel tags: @@ -135,7 +135,7 @@ paths: description: | The ID of the model to use for this request. responses: - "200": + '200': description: OK content: application/json: @@ -147,15 +147,15 @@ paths: curl -X 'GET' \ 'http://localhost:1337/v1/models/download/{model_id}' \ -H 'accept: application/json' - "/models/{model_id}": + /models/{model_id}: get: operationId: retrieveModel tags: - Models summary: Retrieve model description: > - Get a model instance, providing basic information about the model - such as the owner and permissioning. Equivalent to OpenAI's retrieve model. parameters: @@ -168,7 +168,7 @@ paths: description: | The ID of the model to use for this request. responses: - "200": + '200': description: OK content: application/json: @@ -199,7 +199,7 @@ paths: description: | The model id to delete responses: - "200": + '200': description: OK content: application/json: @@ -228,7 +228,7 @@ paths: schema: $ref: specs/threads.yaml#/components/schemas/CreateThreadObject responses: - "200": + '200': description: Thread created successfully content: application/json: @@ -257,7 +257,7 @@ paths: description: | Retrieves a list of all threads available in the system. responses: - "200": + '200': description: List of threads retrieved successfully content: application/json: @@ -285,7 +285,7 @@ paths: source: | curl http://localhost:1337/v1/threads \ -H "Content-Type: application/json" \ - "/threads/{thread_id}": + /threads/{thread_id}: get: operationId: getThread tags: @@ -305,7 +305,7 @@ paths: description: | The ID of the thread to retrieve. responses: - "200": + '200': description: Thread details retrieved successfully content: application/json: @@ -345,7 +345,7 @@ paths: items: $ref: specs/threads.yaml#/components/schemas/ThreadMessageObject responses: - "200": + '200': description: Thread modified successfully content: application/json: @@ -384,7 +384,7 @@ paths: description: | The ID of the thread to be deleted. responses: - "200": + '200': description: Thread deleted successfully content: application/json: @@ -405,7 +405,7 @@ paths: "https://platform.openai.com/docs/api-reference/assistants/listAssistants"> Equivalent to OpenAI's list assistants. responses: - "200": + '200': description: List of assistants retrieved successfully content: application/json: @@ -442,10 +442,36 @@ paths: metadata: {} x-codeSamples: - lang: cURL - source: | + source: |- curl http://localhost:1337/v1/assistants \ - -H "Content-Type: application/json" \ - "/assistants/{assistant_id}": + -H "Content-Type: application/json" + - lang: JavaScript + source: |- + fetch('http://localhost:1337/v1/assistants', { + method: 'GET', + headers: { + 'Content-Type': 'application/json' + } + }) + - lang: Node.js + source: |- + const fetch = require('node-fetch'); + + fetch('http://localhost:1337/v1/assistants', { + method: 'GET', + headers: { + 'Content-Type': 'application/json' + } + }) + - lang: Python + source: |- + import requests + + url = 'http://localhost:1337/v1/assistants' + headers = {'Content-Type': 'application/json'} + + response = requests.get(url, headers=headers) + /assistants/{assistant_id}: get: operationId: getAssistant tags: @@ -465,18 +491,19 @@ paths: description: | The ID of the assistant to retrieve. responses: - "200": + '200': description: null content: application/json: schema: - $ref: specs/assistants.yaml#/components/schemas/RetrieveAssistantResponse + $ref: >- + specs/assistants.yaml#/components/schemas/RetrieveAssistantResponse x-codeSamples: - lang: cURL source: | curl http://localhost:1337/v1/assistants/{assistant_id} \ -H "Content-Type: application/json" \ - "/threads/{thread_id}/messages": + /threads/{thread_id}/messages: get: operationId: listMessages tags: @@ -495,7 +522,7 @@ paths: description: | The ID of the thread from which to retrieve messages. responses: - "200": + '200': description: List of messages retrieved successfully content: application/json: @@ -547,7 +574,7 @@ paths: - role - content responses: - "200": + '200': description: Message created successfully content: application/json: @@ -562,7 +589,7 @@ paths: "role": "user", "content": "How does AI work? Explain it in simple terms." }' - "/threads/{thread_id}/messages/{message_id}": + /threads/{thread_id}/messages/{message_id}: get: operationId: retrieveMessage tags: @@ -589,7 +616,7 @@ paths: description: | The ID of the message to retrieve. responses: - "200": + '200': description: OK content: application/json: @@ -598,8 +625,8 @@ paths: x-codeSamples: - lang: cURL source: > - curl http://localhost:1337/v1/threads/{thread_id}/messages/{message_id} - \ + curl + http://localhost:1337/v1/threads/{thread_id}/messages/{message_id} \ -H "Content-Type: application/json" x-webhooks: ModelObject: @@ -621,10 +648,9 @@ x-webhooks: post: summary: The assistant object description: > - Build assistants that can call models and use tools to perform - tasks. Equivalent - to OpenAI's assistants object. + Build assistants that can call models and use tools to perform tasks. + + Equivalent to OpenAI's assistants object. operationId: AssistantObjects tags: - Assistants @@ -651,7 +677,8 @@ x-webhooks: ThreadObject: post: summary: The thread object - description: Represents a thread that contains messages. - + Represents a thread that contains messages. Equivalent to OpenAI's thread object. operationId: ThreadObject From 11ff9a2a2fe500d41a2fc817ff79be399e532f09 Mon Sep 17 00:00:00 2001 From: avb-is-me <104213687+avb-is-me@users.noreply.github.com> Date: Wed, 28 Feb 2024 16:29:18 +0000 Subject: [PATCH 3/9] adds code samples for the assistant_id endpoints --- docs/openapi/jan.yaml | 128 +++++++++++++++++++++++++++--------------- 1 file changed, 82 insertions(+), 46 deletions(-) diff --git a/docs/openapi/jan.yaml b/docs/openapi/jan.yaml index 864c80fdf..09916415a 100644 --- a/docs/openapi/jan.yaml +++ b/docs/openapi/jan.yaml @@ -1,11 +1,11 @@ ---- openapi: 3.0.0 info: title: API Reference description: > # Introduction - Jan API is compatible with the [OpenAI API](https://platform.openai.com/docs/api-reference). + Jan API is compatible with the [OpenAI + API](https://platform.openai.com/docs/api-reference). version: 0.1.8 contact: name: Jan Discord @@ -20,12 +20,12 @@ tags: description: List and describe the various models available in the API. - name: Chat description: > - Given a list of messages comprising a conversation, the model will - return a response. + Given a list of messages comprising a conversation, the model will return + a response. - name: Messages description: > - Messages capture a conversation's content. This can include the - content from LLM responses and other metadata from [chat + Messages capture a conversation's content. This can include the content + from LLM responses and other metadata from [chat completions](/specs/chats). - name: Threads - name: Assistants @@ -49,16 +49,16 @@ paths: summary: | Create chat completion description: > - Creates a model response for the given chat conversation. - Equivalent to OpenAI's create chat completion. + Creates a model response for the given chat conversation. Equivalent + to OpenAI's create chat completion. requestBody: content: application/json: schema: $ref: specs/chat.yaml#/components/schemas/ChatCompletionRequest responses: - "200": + '200': description: OK content: application/json: @@ -100,12 +100,12 @@ paths: - Models summary: List models description: > - Lists the currently available models, and provides basic - information about each one such as the owner and availability. - Equivalent to OpenAI's list model. + Lists the currently available models, and provides basic information + about each one such as the owner and availability. Equivalent + to OpenAI's list model. responses: - "200": + '200': description: OK content: application/json: @@ -117,7 +117,7 @@ paths: curl -X 'GET' \ 'http://localhost:1337/v1/models' \ -H 'accept: application/json' - "/models/download/{model_id}": + /models/download/{model_id}: get: operationId: downloadModel tags: @@ -135,7 +135,7 @@ paths: description: | The ID of the model to use for this request. responses: - "200": + '200': description: OK content: application/json: @@ -147,15 +147,15 @@ paths: curl -X 'GET' \ 'http://localhost:1337/v1/models/download/{model_id}' \ -H 'accept: application/json' - "/models/{model_id}": + /models/{model_id}: get: operationId: retrieveModel tags: - Models summary: Retrieve model description: > - Get a model instance, providing basic information about the model - such as the owner and permissioning. Equivalent to OpenAI's retrieve model. parameters: @@ -168,7 +168,7 @@ paths: description: | The ID of the model to use for this request. responses: - "200": + '200': description: OK content: application/json: @@ -199,7 +199,7 @@ paths: description: | The model id to delete responses: - "200": + '200': description: OK content: application/json: @@ -228,7 +228,7 @@ paths: schema: $ref: specs/threads.yaml#/components/schemas/CreateThreadObject responses: - "200": + '200': description: Thread created successfully content: application/json: @@ -257,7 +257,7 @@ paths: description: | Retrieves a list of all threads available in the system. responses: - "200": + '200': description: List of threads retrieved successfully content: application/json: @@ -285,7 +285,7 @@ paths: source: | curl http://localhost:1337/v1/threads \ -H "Content-Type: application/json" \ - "/threads/{thread_id}": + /threads/{thread_id}: get: operationId: getThread tags: @@ -305,7 +305,7 @@ paths: description: | The ID of the thread to retrieve. responses: - "200": + '200': description: Thread details retrieved successfully content: application/json: @@ -345,7 +345,7 @@ paths: items: $ref: specs/threads.yaml#/components/schemas/ThreadMessageObject responses: - "200": + '200': description: Thread modified successfully content: application/json: @@ -384,7 +384,7 @@ paths: description: | The ID of the thread to be deleted. responses: - "200": + '200': description: Thread deleted successfully content: application/json: @@ -405,7 +405,7 @@ paths: "https://platform.openai.com/docs/api-reference/assistants/listAssistants"> Equivalent to OpenAI's list assistants. responses: - "200": + '200': description: List of assistants retrieved successfully content: application/json: @@ -445,7 +445,7 @@ paths: source: | curl http://localhost:1337/v1/assistants \ -H "Content-Type: application/json" \ - "/assistants/{assistant_id}": + /assistants/{assistant_id}: get: operationId: getAssistant tags: @@ -465,18 +465,54 @@ paths: description: | The ID of the assistant to retrieve. responses: - "200": + '200': description: null content: application/json: schema: - $ref: specs/assistants.yaml#/components/schemas/RetrieveAssistantResponse + $ref: >- + specs/assistants.yaml#/components/schemas/RetrieveAssistantResponse x-codeSamples: - lang: cURL - source: | + source: |- curl http://localhost:1337/v1/assistants/{assistant_id} \ - -H "Content-Type: application/json" \ - "/threads/{thread_id}/messages": + -H "Content-Type: application/json" + - lang: JavaScript + source: |- + const fetch = require('node-fetch'); + + let assistantId = 'abc123'; + + fetch(`http://localhost:1337/v1/assistants/${assistantId}`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json' + } + }) + - lang: Node.js + source: |- + const fetch = require('node-fetch'); + + let assistantId = 'abc123'; + + fetch(`http://localhost:1337/v1/assistants/${assistantId}`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json' + } + }) + - lang: Python + source: >- + import requests + + + assistant_id = 'abc123' + + + response = + requests.get(f'http://localhost:1337/v1/assistants/{assistant_id}', + headers={'Content-Type': 'application/json'}) + /threads/{thread_id}/messages: get: operationId: listMessages tags: @@ -495,7 +531,7 @@ paths: description: | The ID of the thread from which to retrieve messages. responses: - "200": + '200': description: List of messages retrieved successfully content: application/json: @@ -547,7 +583,7 @@ paths: - role - content responses: - "200": + '200': description: Message created successfully content: application/json: @@ -562,7 +598,7 @@ paths: "role": "user", "content": "How does AI work? Explain it in simple terms." }' - "/threads/{thread_id}/messages/{message_id}": + /threads/{thread_id}/messages/{message_id}: get: operationId: retrieveMessage tags: @@ -589,7 +625,7 @@ paths: description: | The ID of the message to retrieve. responses: - "200": + '200': description: OK content: application/json: @@ -598,8 +634,8 @@ paths: x-codeSamples: - lang: cURL source: > - curl http://localhost:1337/v1/threads/{thread_id}/messages/{message_id} - \ + curl + http://localhost:1337/v1/threads/{thread_id}/messages/{message_id} \ -H "Content-Type: application/json" x-webhooks: ModelObject: @@ -621,10 +657,9 @@ x-webhooks: post: summary: The assistant object description: > - Build assistants that can call models and use tools to perform - tasks. Equivalent - to OpenAI's assistants object. + Build assistants that can call models and use tools to perform tasks. + + Equivalent to OpenAI's assistants object. operationId: AssistantObjects tags: - Assistants @@ -651,7 +686,8 @@ x-webhooks: ThreadObject: post: summary: The thread object - description: Represents a thread that contains messages. - + Represents a thread that contains messages. Equivalent to OpenAI's thread object. operationId: ThreadObject From 02f2536410b73b130d8c5925e108e43b35eb3fa8 Mon Sep 17 00:00:00 2001 From: hieu-jan <150573299+hieu-jan@users.noreply.github.com> Date: Sun, 3 Mar 2024 07:34:10 +0900 Subject: [PATCH 4/9] docs: re-order language support consistency --- docs/openapi/jan.yaml | 94 +++++++++++++++++++------------------------ 1 file changed, 42 insertions(+), 52 deletions(-) diff --git a/docs/openapi/jan.yaml b/docs/openapi/jan.yaml index 3d147299e..d227c018b 100644 --- a/docs/openapi/jan.yaml +++ b/docs/openapi/jan.yaml @@ -1,11 +1,11 @@ +--- openapi: 3.0.0 info: title: API Reference description: > # Introduction - Jan API is compatible with the [OpenAI - API](https://platform.openai.com/docs/api-reference). + Jan API is compatible with the [OpenAI API](https://platform.openai.com/docs/api-reference). version: 0.1.8 contact: name: Jan Discord @@ -20,12 +20,12 @@ tags: description: List and describe the various models available in the API. - name: Chat description: > - Given a list of messages comprising a conversation, the model will return - a response. + Given a list of messages comprising a conversation, the model will + return a response. - name: Messages description: > - Messages capture a conversation's content. This can include the content - from LLM responses and other metadata from [chat + Messages capture a conversation's content. This can include the + content from LLM responses and other metadata from [chat completions](/specs/chats). - name: Threads - name: Assistants @@ -49,9 +49,9 @@ paths: summary: | Create chat completion description: > - Creates a model response for the given chat conversation. Equivalent - to OpenAI's create chat completion. + Creates a model response for the given chat conversation. + Equivalent to OpenAI's create chat completion. requestBody: content: application/json: @@ -192,9 +192,7 @@ paths: } - response = - requests.post('http://localhost:1337/v1/chat/completions', - json=data) + response = requests.post('http://localhost:1337/v1/chat/completions', json=data) print(response.json()) /models: @@ -204,10 +202,10 @@ paths: - Models summary: List models description: > - Lists the currently available models, and provides basic information - about each one such as the owner and availability. Equivalent - to OpenAI's list model. + Lists the currently available models, and provides basic + information about each one such as the owner and availability. + Equivalent to OpenAI's list model. responses: '200': description: OK @@ -228,14 +226,7 @@ paths: headers: {Accept: 'application/json'} }); const data = await response.json(); - - lang: Python - source: |- - import requests - url = 'http://localhost:1337/v1/models' - headers = {'Accept': 'application/json'} - response = requests.get(url, headers=headers) - data = response.json() - lang: Node.js source: |- const fetch = require('node-fetch'); @@ -249,7 +240,15 @@ paths: fetch(url, options) .then(res => res.json()) .then(json => console.log(json)); - /models/download/{model_id}: + - lang: Python + source: |- + import requests + + url = 'http://localhost:1337/v1/models' + headers = {'Accept': 'application/json'} + response = requests.get(url, headers=headers) + data = response.json() + '/models/download/{model_id}': get: operationId: downloadModel tags: @@ -304,20 +303,18 @@ paths: import requests - response = - requests.get('http://localhost:1337/v1/models/download/{model_id}', - headers={'accept': 'application/json'}) + response = requests.get('http://localhost:1337/v1/models/download/{model_id}', headers={'accept': 'application/json'}) data = response.json() - /models/{model_id}: + '/models/{model_id}': get: operationId: retrieveModel tags: - Models summary: Retrieve model description: > - Get a model instance, providing basic information about the model such - as the owner and permissioning. Equivalent to OpenAI's retrieve model. parameters: @@ -374,9 +371,7 @@ paths: model_id = 'mistral-ins-7b-q4' - response = - requests.get(f'http://localhost:1337/v1/models/{model_id}', - headers={'accept': 'application/json'}) + response = requests.get(f'http://localhost:1337/v1/models/{model_id}', headers={'accept': 'application/json'}) print(response.json()) delete: @@ -442,9 +437,7 @@ paths: model_id = 'mistral-ins-7b-q4' - response = - requests.delete(f'http://localhost:1337/v1/models/{model_id}', - headers={'accept': 'application/json'}) + response = requests.delete(f'http://localhost:1337/v1/models/{model_id}', headers={'accept': 'application/json'}) /threads: post: operationId: createThread @@ -613,7 +606,7 @@ paths: response = requests.get(url, headers=headers) print(response.json()) - /threads/{thread_id}: + '/threads/{thread_id}': get: operationId: getThread tags: @@ -799,7 +792,7 @@ paths: headers = {'Content-Type': 'application/json'} response = requests.get(url, headers=headers) - /assistants/{assistant_id}: + '/assistants/{assistant_id}': get: operationId: getAssistant tags: @@ -824,8 +817,7 @@ paths: content: application/json: schema: - $ref: >- - specs/assistants.yaml#/components/schemas/RetrieveAssistantResponse + $ref: specs/assistants.yaml#/components/schemas/RetrieveAssistantResponse x-codeSamples: - lang: cURL source: |- @@ -863,10 +855,8 @@ paths: assistant_id = 'abc123' - response = - requests.get(f'http://localhost:1337/v1/assistants/{assistant_id}', - headers={'Content-Type': 'application/json'}) - /threads/{thread_id}/messages: + response = requests.get(f'http://localhost:1337/v1/assistants/{assistant_id}', headers={'Content-Type': 'application/json'}) + '/threads/{thread_id}/messages': get: operationId: listMessages tags: @@ -952,7 +942,7 @@ paths: "role": "user", "content": "How does AI work? Explain it in simple terms." }' - /threads/{thread_id}/messages/{message_id}: + '/threads/{thread_id}/messages/{message_id}': get: operationId: retrieveMessage tags: @@ -988,8 +978,8 @@ paths: x-codeSamples: - lang: cURL source: > - curl - http://localhost:1337/v1/threads/{thread_id}/messages/{message_id} \ + curl http://localhost:1337/v1/threads/{thread_id}/messages/{message_id} + \ -H "Content-Type: application/json" x-webhooks: ModelObject: @@ -1011,9 +1001,10 @@ x-webhooks: post: summary: The assistant object description: > - Build assistants that can call models and use tools to perform tasks. - - Equivalent to OpenAI's assistants object. + Build assistants that can call models and use tools to perform + tasks. Equivalent + to OpenAI's assistants object. operationId: AssistantObjects tags: - Assistants @@ -1040,8 +1031,7 @@ x-webhooks: ThreadObject: post: summary: The thread object - description: >- - Represents a thread that contains messages. Equivalent to OpenAI's thread object. operationId: ThreadObject From 497020c7a355ea3169d2807eff6fbc981fddbc34 Mon Sep 17 00:00:00 2001 From: hieu-jan <150573299+hieu-jan@users.noreply.github.com> Date: Sun, 3 Mar 2024 07:39:39 +0900 Subject: [PATCH 5/9] docs: yaml lint --- docs/openapi/jan.yaml | 43 +++++++++++++++++++++---------------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/docs/openapi/jan.yaml b/docs/openapi/jan.yaml index d227c018b..f45db7d2d 100644 --- a/docs/openapi/jan.yaml +++ b/docs/openapi/jan.yaml @@ -58,7 +58,7 @@ paths: schema: $ref: specs/chat.yaml#/components/schemas/ChatCompletionRequest responses: - '200': + "200": description: OK content: application/json: @@ -207,7 +207,7 @@ paths: = "https://platform.openai.com/docs/api-reference/models/list"> Equivalent to OpenAI's list model. responses: - '200': + "200": description: OK content: application/json: @@ -226,7 +226,6 @@ paths: headers: {Accept: 'application/json'} }); const data = await response.json(); - - lang: Node.js source: |- const fetch = require('node-fetch'); @@ -248,7 +247,7 @@ paths: headers = {'Accept': 'application/json'} response = requests.get(url, headers=headers) data = response.json() - '/models/download/{model_id}': + "/models/download/{model_id}": get: operationId: downloadModel tags: @@ -266,7 +265,7 @@ paths: description: | The ID of the model to use for this request. responses: - '200': + "200": description: OK content: application/json: @@ -306,7 +305,7 @@ paths: response = requests.get('http://localhost:1337/v1/models/download/{model_id}', headers={'accept': 'application/json'}) data = response.json() - '/models/{model_id}': + "/models/{model_id}": get: operationId: retrieveModel tags: @@ -327,7 +326,7 @@ paths: description: | The ID of the model to use for this request. responses: - '200': + "200": description: OK content: application/json: @@ -393,7 +392,7 @@ paths: description: | The model id to delete responses: - '200': + "200": description: OK content: application/json: @@ -455,7 +454,7 @@ paths: schema: $ref: specs/threads.yaml#/components/schemas/CreateThreadObject responses: - '200': + "200": description: Thread created successfully content: application/json: @@ -551,7 +550,7 @@ paths: description: | Retrieves a list of all threads available in the system. responses: - '200': + "200": description: List of threads retrieved successfully content: application/json: @@ -606,7 +605,7 @@ paths: response = requests.get(url, headers=headers) print(response.json()) - '/threads/{thread_id}': + "/threads/{thread_id}": get: operationId: getThread tags: @@ -626,7 +625,7 @@ paths: description: | The ID of the thread to retrieve. responses: - '200': + "200": description: Thread details retrieved successfully content: application/json: @@ -666,7 +665,7 @@ paths: items: $ref: specs/threads.yaml#/components/schemas/ThreadMessageObject responses: - '200': + "200": description: Thread modified successfully content: application/json: @@ -705,7 +704,7 @@ paths: description: | The ID of the thread to be deleted. responses: - '200': + "200": description: Thread deleted successfully content: application/json: @@ -726,7 +725,7 @@ paths: "https://platform.openai.com/docs/api-reference/assistants/listAssistants"> Equivalent to OpenAI's list assistants. responses: - '200': + "200": description: List of assistants retrieved successfully content: application/json: @@ -792,7 +791,7 @@ paths: headers = {'Content-Type': 'application/json'} response = requests.get(url, headers=headers) - '/assistants/{assistant_id}': + "/assistants/{assistant_id}": get: operationId: getAssistant tags: @@ -812,7 +811,7 @@ paths: description: | The ID of the assistant to retrieve. responses: - '200': + "200": description: null content: application/json: @@ -856,7 +855,7 @@ paths: response = requests.get(f'http://localhost:1337/v1/assistants/{assistant_id}', headers={'Content-Type': 'application/json'}) - '/threads/{thread_id}/messages': + "/threads/{thread_id}/messages": get: operationId: listMessages tags: @@ -875,7 +874,7 @@ paths: description: | The ID of the thread from which to retrieve messages. responses: - '200': + "200": description: List of messages retrieved successfully content: application/json: @@ -927,7 +926,7 @@ paths: - role - content responses: - '200': + "200": description: Message created successfully content: application/json: @@ -942,7 +941,7 @@ paths: "role": "user", "content": "How does AI work? Explain it in simple terms." }' - '/threads/{thread_id}/messages/{message_id}': + "/threads/{thread_id}/messages/{message_id}": get: operationId: retrieveMessage tags: @@ -969,7 +968,7 @@ paths: description: | The ID of the message to retrieve. responses: - '200': + "200": description: OK content: application/json: From 52f84dce9ff737e2ff4f2042708eca758fba0bdc Mon Sep 17 00:00:00 2001 From: NamH Date: Sun, 3 Mar 2024 17:54:01 +0700 Subject: [PATCH 6/9] chore: clean up some redundant code (#2215) Signed-off-by: James Co-authored-by: James --- web/containers/Providers/index.tsx | 18 ++-- web/context/FeatureToggle.tsx | 104 ------------------------ web/helpers/atoms/ApiServer.atom.ts | 16 ++++ web/helpers/atoms/AppConfig.atom.ts | 18 ++++ web/hooks/useConvertHuggingFaceModel.ts | 10 +-- web/hooks/useCreateNewThread.ts | 10 +-- web/hooks/useDownloadModel.ts | 15 ++-- web/screens/Chat/ChatInput/index.tsx | 7 +- web/screens/Chat/Sidebar/index.tsx | 10 +-- web/screens/Chat/index.tsx | 7 +- web/screens/ExploreModels/index.tsx | 7 +- web/screens/LocalServer/index.tsx | 32 ++++---- web/screens/Settings/Advanced/index.tsx | 46 +++++------ 13 files changed, 109 insertions(+), 191 deletions(-) delete mode 100644 web/context/FeatureToggle.tsx create mode 100644 web/helpers/atoms/ApiServer.atom.ts diff --git a/web/containers/Providers/index.tsx b/web/containers/Providers/index.tsx index e7a179ec4..73445f10a 100644 --- a/web/containers/Providers/index.tsx +++ b/web/containers/Providers/index.tsx @@ -11,8 +11,6 @@ import EventListenerWrapper from '@/containers/Providers/EventListener' import JotaiWrapper from '@/containers/Providers/Jotai' import ThemeWrapper from '@/containers/Providers/Theme' -import FeatureToggleWrapper from '@/context/FeatureToggle' - import { setupCoreServices } from '@/services/coreService' import { isCoreExtensionInstalled, @@ -81,15 +79,13 @@ const Providers = (props: PropsWithChildren) => { {settingUp && } {setupCore && activated && ( - - - - {children} - - {!isMac && } - - - + + + {children} + + {!isMac && } + + )} diff --git a/web/context/FeatureToggle.tsx b/web/context/FeatureToggle.tsx deleted file mode 100644 index 5a63eb66e..000000000 --- a/web/context/FeatureToggle.tsx +++ /dev/null @@ -1,104 +0,0 @@ -import { createContext, ReactNode, useEffect, useState } from 'react' - -interface FeatureToggleContextType { - experimentalFeature: boolean - ignoreSSL: boolean - proxy: string - proxyEnabled: boolean - vulkanEnabled: boolean - setExperimentalFeature: (on: boolean) => void - setVulkanEnabled: (on: boolean) => void - setIgnoreSSL: (on: boolean) => void - setProxy: (value: string) => void - setProxyEnabled: (on: boolean) => void -} - -const initialContext: FeatureToggleContextType = { - experimentalFeature: false, - ignoreSSL: false, - proxy: '', - proxyEnabled: false, - vulkanEnabled: false, - setExperimentalFeature: () => {}, - setVulkanEnabled: () => {}, - setIgnoreSSL: () => {}, - setProxy: () => {}, - setProxyEnabled: () => {}, -} - -export const FeatureToggleContext = - createContext(initialContext) - -export default function FeatureToggleWrapper({ - children, -}: { - children: ReactNode -}) { - const EXPERIMENTAL_FEATURE = 'experimentalFeature' - const VULKAN_ENABLED = 'vulkanEnabled' - const IGNORE_SSL = 'ignoreSSLFeature' - const HTTPS_PROXY_FEATURE = 'httpsProxyFeature' - const PROXY_FEATURE_ENABLED = 'proxyFeatureEnabled' - - const [experimentalFeature, directSetExperimentalFeature] = - useState(false) - const [proxyEnabled, directSetProxyEnabled] = useState(false) - const [vulkanEnabled, directEnableVulkan] = useState(false) - const [ignoreSSL, directSetIgnoreSSL] = useState(false) - const [proxy, directSetProxy] = useState('') - - useEffect(() => { - directSetExperimentalFeature( - localStorage.getItem(EXPERIMENTAL_FEATURE) === 'true' - ) - directSetIgnoreSSL(localStorage.getItem(IGNORE_SSL) === 'true') - directSetProxy(localStorage.getItem(HTTPS_PROXY_FEATURE) ?? '') - directSetProxyEnabled( - localStorage.getItem(PROXY_FEATURE_ENABLED) === 'true' - ) - }, []) - - const setExperimentalFeature = (on: boolean) => { - localStorage.setItem(EXPERIMENTAL_FEATURE, on ? 'true' : 'false') - directSetExperimentalFeature(on) - } - - const setVulkanEnabled = (on: boolean) => { - localStorage.setItem(VULKAN_ENABLED, on ? 'true' : 'false') - directEnableVulkan(on) - } - - const setIgnoreSSL = (on: boolean) => { - localStorage.setItem(IGNORE_SSL, on ? 'true' : 'false') - directSetIgnoreSSL(on) - } - - const setProxy = (proxy: string) => { - localStorage.setItem(HTTPS_PROXY_FEATURE, proxy) - directSetProxy(proxy) - } - - const setProxyEnabled = (on: boolean) => { - localStorage.setItem(PROXY_FEATURE_ENABLED, on ? 'true' : 'false') - directSetProxyEnabled(on) - } - - return ( - - {children} - - ) -} diff --git a/web/helpers/atoms/ApiServer.atom.ts b/web/helpers/atoms/ApiServer.atom.ts new file mode 100644 index 000000000..2ccd2de23 --- /dev/null +++ b/web/helpers/atoms/ApiServer.atom.ts @@ -0,0 +1,16 @@ +import { atomWithStorage } from 'jotai/utils' + +export const hostOptions = ['127.0.0.1', '0.0.0.0'] + +export const apiServerPortAtom = atomWithStorage('apiServerPort', '1337') +export const apiServerHostAtom = atomWithStorage('apiServerHost', '127.0.0.1') + +export const apiServerCorsEnabledAtom = atomWithStorage( + 'apiServerCorsEnabled', + true +) + +export const apiServerVerboseLogEnabledAtom = atomWithStorage( + 'apiServerVerboseLogEnabled', + true +) diff --git a/web/helpers/atoms/AppConfig.atom.ts b/web/helpers/atoms/AppConfig.atom.ts index 9dfdfca90..75343d722 100644 --- a/web/helpers/atoms/AppConfig.atom.ts +++ b/web/helpers/atoms/AppConfig.atom.ts @@ -1,3 +1,21 @@ import { atom } from 'jotai' +import { atomWithStorage } from 'jotai/utils' + +const EXPERIMENTAL_FEATURE = 'experimentalFeature' +const PROXY_FEATURE_ENABLED = 'proxyFeatureEnabled' +const VULKAN_ENABLED = 'vulkanEnabled' +const IGNORE_SSL = 'ignoreSSLFeature' +const HTTPS_PROXY_FEATURE = 'httpsProxyFeature' export const janDataFolderPathAtom = atom('') + +export const experimentalFeatureEnabledAtom = atomWithStorage( + EXPERIMENTAL_FEATURE, + false +) + +export const proxyEnabledAtom = atomWithStorage(PROXY_FEATURE_ENABLED, false) +export const proxyAtom = atomWithStorage(HTTPS_PROXY_FEATURE, '') + +export const ignoreSslAtom = atomWithStorage(IGNORE_SSL, false) +export const vulkanEnabledAtom = atomWithStorage(VULKAN_ENABLED, false) diff --git a/web/hooks/useConvertHuggingFaceModel.ts b/web/hooks/useConvertHuggingFaceModel.ts index bbf33207b..0616c4ee7 100644 --- a/web/hooks/useConvertHuggingFaceModel.ts +++ b/web/hooks/useConvertHuggingFaceModel.ts @@ -1,5 +1,3 @@ -import { useContext } from 'react' - import { ExtensionTypeEnum, HuggingFaceExtension, @@ -7,18 +5,18 @@ import { Quantization, } from '@janhq/core' -import { useSetAtom } from 'jotai' - -import { FeatureToggleContext } from '@/context/FeatureToggle' +import { useAtomValue, useSetAtom } from 'jotai' import { extensionManager } from '@/extension/ExtensionManager' +import { ignoreSslAtom, proxyAtom } from '@/helpers/atoms/AppConfig.atom' import { conversionStatusAtom, conversionErrorAtom, } from '@/helpers/atoms/HFConverter.atom' export const useConvertHuggingFaceModel = () => { - const { ignoreSSL, proxy } = useContext(FeatureToggleContext) + const proxy = useAtomValue(proxyAtom) + const ignoreSSL = useAtomValue(ignoreSslAtom) const setConversionStatus = useSetAtom(conversionStatusAtom) const setConversionError = useSetAtom(conversionErrorAtom) diff --git a/web/hooks/useCreateNewThread.ts b/web/hooks/useCreateNewThread.ts index 722e5b7e4..247c65c55 100644 --- a/web/hooks/useCreateNewThread.ts +++ b/web/hooks/useCreateNewThread.ts @@ -1,5 +1,3 @@ -import { useContext } from 'react' - import { Assistant, ConversationalExtension, @@ -17,8 +15,6 @@ import { atom, useAtomValue, useSetAtom } from 'jotai' import { selectedModelAtom } from '@/containers/DropdownListSidebar' import { fileUploadAtom } from '@/containers/Providers/Jotai' -import { FeatureToggleContext } from '@/context/FeatureToggle' - import { generateThreadId } from '@/utils/thread' import useRecommendedModel from './useRecommendedModel' @@ -27,6 +23,7 @@ import useSetActiveThread from './useSetActiveThread' import { extensionManager } from '@/extension' +import { experimentalFeatureEnabledAtom } from '@/helpers/atoms/AppConfig.atom' import { threadsAtom, threadStatesAtom, @@ -59,7 +56,8 @@ export const useCreateNewThread = () => { const setFileUpload = useSetAtom(fileUploadAtom) const setSelectedModel = useSetAtom(selectedModelAtom) const setThreadModelParams = useSetAtom(setThreadModelParamsAtom) - const { experimentalFeature } = useContext(FeatureToggleContext) + + const experimentalEnabled = useAtomValue(experimentalFeatureEnabledAtom) const setIsGeneratingResponse = useSetAtom(isGeneratingResponseAtom) const { recommendedModel, downloadedModels } = useRecommendedModel() @@ -94,7 +92,7 @@ export const useCreateNewThread = () => { const assistantInfo: ThreadAssistantInfo = { assistant_id: assistant.id, assistant_name: assistant.name, - tools: experimentalFeature ? [assistantTools] : assistant.tools, + tools: experimentalEnabled ? [assistantTools] : assistant.tools, model: { id: defaultModel?.id ?? '*', settings: defaultModel?.settings ?? {}, diff --git a/web/hooks/useDownloadModel.ts b/web/hooks/useDownloadModel.ts index 59333fbde..9f6334c71 100644 --- a/web/hooks/useDownloadModel.ts +++ b/web/hooks/useDownloadModel.ts @@ -1,4 +1,4 @@ -import { useCallback, useContext } from 'react' +import { useCallback } from 'react' import { Model, @@ -10,17 +10,22 @@ import { DownloadState, } from '@janhq/core' -import { useSetAtom } from 'jotai' - -import { FeatureToggleContext } from '@/context/FeatureToggle' +import { useAtomValue, useSetAtom } from 'jotai' import { setDownloadStateAtom } from './useDownloadState' import { extensionManager } from '@/extension/ExtensionManager' +import { + ignoreSslAtom, + proxyAtom, + proxyEnabledAtom, +} from '@/helpers/atoms/AppConfig.atom' import { addDownloadingModelAtom } from '@/helpers/atoms/Model.atom' export default function useDownloadModel() { - const { ignoreSSL, proxy, proxyEnabled } = useContext(FeatureToggleContext) + const ignoreSSL = useAtomValue(ignoreSslAtom) + const proxy = useAtomValue(proxyAtom) + const proxyEnabled = useAtomValue(proxyEnabledAtom) const setDownloadState = useSetAtom(setDownloadStateAtom) const addDownloadingModel = useSetAtom(addDownloadingModelAtom) diff --git a/web/screens/Chat/ChatInput/index.tsx b/web/screens/Chat/ChatInput/index.tsx index 5b8128439..d5334cab8 100644 --- a/web/screens/Chat/ChatInput/index.tsx +++ b/web/screens/Chat/ChatInput/index.tsx @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { useContext, useEffect, useRef, useState } from 'react' +import { useEffect, useRef, useState } from 'react' import { InferenceEvent, MessageStatus, events } from '@janhq/core' @@ -24,8 +24,6 @@ import { twMerge } from 'tailwind-merge' import { currentPromptAtom, fileUploadAtom } from '@/containers/Providers/Jotai' -import { FeatureToggleContext } from '@/context/FeatureToggle' - import { useActiveModel } from '@/hooks/useActiveModel' import { useClickOutside } from '@/hooks/useClickOutside' @@ -34,6 +32,7 @@ import useSendChatMessage from '@/hooks/useSendChatMessage' import FileUploadPreview from '../FileUploadPreview' import ImageUploadPreview from '../ImageUploadPreview' +import { experimentalFeatureEnabledAtom } from '@/helpers/atoms/AppConfig.atom' import { getCurrentChatMessagesAtom } from '@/helpers/atoms/ChatMessage.atom' import { activeThreadAtom, @@ -58,7 +57,7 @@ const ChatInput: React.FC = () => { const fileInputRef = useRef(null) const imageInputRef = useRef(null) const [showAttacmentMenus, setShowAttacmentMenus] = useState(false) - const { experimentalFeature } = useContext(FeatureToggleContext) + const experimentalFeature = useAtomValue(experimentalFeatureEnabledAtom) const isGeneratingResponse = useAtomValue(isGeneratingResponseAtom) const threadStates = useAtomValue(threadStatesAtom) diff --git a/web/screens/Chat/Sidebar/index.tsx b/web/screens/Chat/Sidebar/index.tsx index 4f7e1bd50..2ff5a1253 100644 --- a/web/screens/Chat/Sidebar/index.tsx +++ b/web/screens/Chat/Sidebar/index.tsx @@ -1,5 +1,4 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -import React, { useContext } from 'react' +import React from 'react' import { Input, @@ -24,8 +23,6 @@ import DropdownListSidebar, { selectedModelAtom, } from '@/containers/DropdownListSidebar' -import { FeatureToggleContext } from '@/context/FeatureToggle' - import { useCreateNewThread } from '@/hooks/useCreateNewThread' import { getConfigurationsData } from '@/utils/componentSettings' @@ -37,6 +34,7 @@ import ModelSetting from '../ModelSetting' import SettingComponentBuilder from '../ModelSetting/SettingComponent' +import { experimentalFeatureEnabledAtom } from '@/helpers/atoms/AppConfig.atom' import { activeThreadAtom, getActiveThreadModelParamsAtom, @@ -50,7 +48,7 @@ const Sidebar: React.FC = () => { const activeModelParams = useAtomValue(getActiveThreadModelParamsAtom) const selectedModel = useAtomValue(selectedModelAtom) const { updateThreadMetadata } = useCreateNewThread() - const { experimentalFeature } = useContext(FeatureToggleContext) + const experimentalFeature = useAtomValue(experimentalFeatureEnabledAtom) const modelEngineParams = toSettingParams(activeModelParams) const modelRuntimeParams = toRuntimeParams(activeModelParams) @@ -174,7 +172,7 @@ const Sidebar: React.FC = () => {
x.name === 'prompt_template'} + selector={(x) => x.name === 'prompt_template'} />
diff --git a/web/screens/Chat/index.tsx b/web/screens/Chat/index.tsx index 125e58b3b..00bca550f 100644 --- a/web/screens/Chat/index.tsx +++ b/web/screens/Chat/index.tsx @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/naming-convention */ -import React, { useContext, useEffect, useState } from 'react' +import React, { useEffect, useState } from 'react' import { useDropzone } from 'react-dropzone' @@ -18,8 +18,6 @@ import { showLeftSideBarAtom } from '@/containers/Providers/KeyListener' import { snackbar } from '@/containers/Toast' -import { FeatureToggleContext } from '@/context/FeatureToggle' - import { activeModelAtom } from '@/hooks/useActiveModel' import { queuedMessageAtom, reloadModelAtom } from '@/hooks/useSendChatMessage' @@ -31,6 +29,7 @@ import ChatInput from './ChatInput' import RequestDownloadModel from './RequestDownloadModel' import Sidebar from './Sidebar' +import { experimentalFeatureEnabledAtom } from '@/helpers/atoms/AppConfig.atom' import { activeThreadAtom, engineParamsUpdateAtom, @@ -63,7 +62,7 @@ const ChatScreen: React.FC = () => { const reloadModel = useAtomValue(reloadModelAtom) const [dragRejected, setDragRejected] = useState({ code: '' }) const setFileUpload = useSetAtom(fileUploadAtom) - const { experimentalFeature } = useContext(FeatureToggleContext) + const experimentalFeature = useAtomValue(experimentalFeatureEnabledAtom) const activeModel = useAtomValue(activeModelAtom) diff --git a/web/screens/ExploreModels/index.tsx b/web/screens/ExploreModels/index.tsx index e7fd3a9dc..a949e9ffb 100644 --- a/web/screens/ExploreModels/index.tsx +++ b/web/screens/ExploreModels/index.tsx @@ -1,4 +1,4 @@ -import { useCallback, useContext, useState } from 'react' +import { useCallback, useState } from 'react' import { Input, @@ -15,13 +15,12 @@ import { import { useAtomValue, useSetAtom } from 'jotai' import { UploadIcon, SearchIcon } from 'lucide-react' -import { FeatureToggleContext } from '@/context/FeatureToggle' - import { setImportModelStageAtom } from '@/hooks/useImportModel' import ExploreModelList from './ExploreModelList' import { HuggingFaceModal } from './HuggingFaceModal' +import { experimentalFeatureEnabledAtom } from '@/helpers/atoms/AppConfig.atom' import { configuredModelsAtom, downloadedModelsAtom, @@ -38,7 +37,7 @@ const ExploreModelsScreen = () => { const [showHuggingFaceModal, setShowHuggingFaceModal] = useState(false) const setImportModelStage = useSetAtom(setImportModelStageAtom) - const { experimentalFeature } = useContext(FeatureToggleContext) + const experimentalFeature = useAtomValue(experimentalFeatureEnabledAtom) const filteredModels = configuredModels.filter((x) => { if (sortSelected === 'Downloaded') { diff --git a/web/screens/LocalServer/index.tsx b/web/screens/LocalServer/index.tsx index 3a8668770..66b6046a1 100644 --- a/web/screens/LocalServer/index.tsx +++ b/web/screens/LocalServer/index.tsx @@ -20,7 +20,7 @@ import { SelectValue, } from '@janhq/uikit' -import { atom, useAtom, useAtomValue, useSetAtom } from 'jotai' +import { useAtom, useAtomValue, useSetAtom } from 'jotai' import { Paintbrush, CodeIcon } from 'lucide-react' import { ExternalLinkIcon, InfoIcon } from 'lucide-react' @@ -53,13 +53,15 @@ import SettingComponentBuilder from '../Chat/ModelSetting/SettingComponent' import { showRightSideBarAtom } from '../Chat/Sidebar' +import { + apiServerCorsEnabledAtom, + apiServerHostAtom, + apiServerPortAtom, + apiServerVerboseLogEnabledAtom, + hostOptions, +} from '@/helpers/atoms/ApiServer.atom' import { serverEnabledAtom } from '@/helpers/atoms/LocalServer.atom' -const corsEnabledAtom = atom(true) -const verboseEnabledAtom = atom(true) -const hostAtom = atom('127.0.0.1') -const portAtom = atom('1337') - const LocalServerScreen = () => { const [errorRangePort, setErrorRangePort] = useState(false) const [serverEnabled, setServerEnabled] = useAtom(serverEnabledAtom) @@ -73,14 +75,14 @@ const LocalServerScreen = () => { const modelEngineParams = toSettingParams(selectedModel?.settings) const componentDataEngineSetting = getConfigurationsData(modelEngineParams) - const [isCorsEnabled, setIsCorsEnabled] = useAtom(corsEnabledAtom) - const [isVerboseEnabled, setIsVerboseEnabled] = useAtom(verboseEnabledAtom) - const [host, setHost] = useAtom(hostAtom) - const [port, setPort] = useAtom(portAtom) + const [isCorsEnabled, setIsCorsEnabled] = useAtom(apiServerCorsEnabledAtom) + const [isVerboseEnabled, setIsVerboseEnabled] = useAtom( + apiServerVerboseLogEnabledAtom + ) + const [host, setHost] = useAtom(apiServerHostAtom) + const [port, setPort] = useAtom(apiServerPortAtom) const [loadModelError, setLoadModelError] = useAtom(loadModelErrorAtom) - const hostOptions = ['127.0.0.1', '0.0.0.0'] - const FIRST_TIME_VISIT_API_SERVER = 'firstTimeVisitAPIServer' const [firstTimeVisitAPIServer, setFirstTimeVisitAPIServer] = @@ -88,11 +90,7 @@ const LocalServerScreen = () => { const handleChangePort = useCallback( (value: string) => { - if (Number(value) <= 0 || Number(value) >= 65536) { - setErrorRangePort(true) - } else { - setErrorRangePort(false) - } + setErrorRangePort(Number(value) <= 0 || Number(value) >= 65536) setPort(value) }, [setPort] diff --git a/web/screens/Settings/Advanced/index.tsx b/web/screens/Settings/Advanced/index.tsx index 9aa204999..a1b377024 100644 --- a/web/screens/Settings/Advanced/index.tsx +++ b/web/screens/Settings/Advanced/index.tsx @@ -1,12 +1,6 @@ 'use client' -import { - useContext, - useEffect, - useState, - useCallback, - ChangeEvent, -} from 'react' +import { useEffect, useState, useCallback, ChangeEvent } from 'react' import { openExternalUrl, fs } from '@janhq/core' @@ -29,20 +23,27 @@ import { ScrollArea, } from '@janhq/uikit' +import { useAtom } from 'jotai' import { AlertTriangleIcon, AlertCircleIcon } from 'lucide-react' import ShortcutModal from '@/containers/ShortcutModal' import { snackbar, toaster } from '@/containers/Toast' -import { FeatureToggleContext } from '@/context/FeatureToggle' - import { useActiveModel } from '@/hooks/useActiveModel' import { useSettings } from '@/hooks/useSettings' import DataFolder from './DataFolder' import FactoryReset from './FactoryReset' +import { + experimentalFeatureEnabledAtom, + ignoreSslAtom, + proxyAtom, + proxyEnabledAtom, + vulkanEnabledAtom, +} from '@/helpers/atoms/AppConfig.atom' + type GPU = { id: string vram: number | null @@ -50,22 +51,19 @@ type GPU = { } const Advanced = () => { - const { - experimentalFeature, - setExperimentalFeature, - ignoreSSL, - setIgnoreSSL, - proxy, - setProxy, - proxyEnabled, - setProxyEnabled, - vulkanEnabled, - setVulkanEnabled, - } = useContext(FeatureToggleContext) + const [experimentalEnabled, setExperimentalEnabled] = useAtom( + experimentalFeatureEnabledAtom + ) + const [vulkanEnabled, setVulkanEnabled] = useAtom(vulkanEnabledAtom) + const [proxyEnabled, setProxyEnabled] = useAtom(proxyEnabledAtom) + const [proxy, setProxy] = useAtom(proxyAtom) + const [ignoreSSL, setIgnoreSSL] = useAtom(ignoreSslAtom) + const [partialProxy, setPartialProxy] = useState(proxy) const [gpuEnabled, setGpuEnabled] = useState(false) const [gpuList, setGpuList] = useState([]) const [gpusInUse, setGpusInUse] = useState([]) + const { readSettings, saveSettings, validateSettings, setShowNotification } = useSettings() const { stopModel } = useActiveModel() @@ -169,8 +167,8 @@ const Advanced = () => {

@@ -355,7 +353,7 @@ const Advanced = () => { )} {/* Vulkan for AMD GPU/ APU and Intel Arc GPU */} - {!isMac && experimentalFeature && ( + {!isMac && experimentalEnabled && (
From b70e7fb91731e2b48f5e3ae5bd25a6d79cf99a69 Mon Sep 17 00:00:00 2001 From: NamH Date: Sun, 3 Mar 2024 20:38:01 +0700 Subject: [PATCH 7/9] fix: comment from QA regarding import model (#2213) Signed-off-by: James Co-authored-by: James --- electron/handlers/native.ts | 6 ++-- web/containers/ItemCardSidebar/index.tsx | 29 --------------- web/hooks/useDropModelBinaries.ts | 2 +- .../Settings/EditModelInfoModal/index.tsx | 25 ++++++++----- .../Settings/SelectingModelModal/index.tsx | 35 ++++++++++++++----- 5 files changed, 46 insertions(+), 51 deletions(-) delete mode 100644 web/containers/ItemCardSidebar/index.tsx diff --git a/electron/handlers/native.ts b/electron/handlers/native.ts index 79fa994bf..19a473e73 100644 --- a/electron/handlers/native.ts +++ b/electron/handlers/native.ts @@ -93,12 +93,12 @@ export function handleAppIPCs() { const { canceled, filePaths } = await dialog.showOpenDialog(mainWindow, { title: 'Select model files', buttonLabel: 'Select', - properties: ['openFile', 'multiSelections'], + properties: ['openFile', 'openDirectory', 'multiSelections'], }) if (canceled) { return - } else { - return filePaths } + + return filePaths }) } diff --git a/web/containers/ItemCardSidebar/index.tsx b/web/containers/ItemCardSidebar/index.tsx deleted file mode 100644 index 627d7f45d..000000000 --- a/web/containers/ItemCardSidebar/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -type Props = { - title: string - description?: string - disabled?: boolean - onChange?: (text?: string) => void -} - -export default function ItemCardSidebar({ - description, - title, - disabled, - onChange, -}: Props) { - return ( -
-
- {title} -
- onChange?.(e.target.value)} - /> -
- ) -} diff --git a/web/hooks/useDropModelBinaries.ts b/web/hooks/useDropModelBinaries.ts index c08e1dc73..d87e96627 100644 --- a/web/hooks/useDropModelBinaries.ts +++ b/web/hooks/useDropModelBinaries.ts @@ -39,7 +39,7 @@ export default function useDropModelBinaries() { })) if (unsupportedFiles.length > 0) { snackbar({ - description: `File has to be a .gguf file`, + description: `Only files with .gguf extension can be imported.`, type: 'error', }) } diff --git a/web/screens/Settings/EditModelInfoModal/index.tsx b/web/screens/Settings/EditModelInfoModal/index.tsx index bc9d6521d..7625ae9fd 100644 --- a/web/screens/Settings/EditModelInfoModal/index.tsx +++ b/web/screens/Settings/EditModelInfoModal/index.tsx @@ -116,6 +116,11 @@ const EditModelInfoModal: React.FC = () => { return null } + const onTagsChange = (e: React.ChangeEvent) => { + const tags = e.target.value.split(',') + setTags(tags) + } + return ( {
- +
-
+

{editingModel.name}

{toGibibytes(editingModel.size)} - - Format:{' '} - - - {editingModel.format.toUpperCase()} - +
+ + Format: + + + {editingModel.format.toUpperCase()} + +
@@ -189,7 +196,7 @@ const EditModelInfoModal: React.FC = () => {
- +
diff --git a/web/screens/Settings/SelectingModelModal/index.tsx b/web/screens/Settings/SelectingModelModal/index.tsx index 35bd9b772..c5b292ea7 100644 --- a/web/screens/Settings/SelectingModelModal/index.tsx +++ b/web/screens/Settings/SelectingModelModal/index.tsx @@ -1,7 +1,7 @@ import { useCallback } from 'react' import { useDropzone } from 'react-dropzone' -import { ImportingModel, baseName, fs } from '@janhq/core' +import { ImportingModel, baseName, fs, joinPath } from '@janhq/core' import { Modal, ModalContent, ModalHeader, ModalTitle } from '@janhq/uikit' import { useAtomValue, useSetAtom } from 'jotai' @@ -34,14 +34,31 @@ const SelectingModelModal: React.FC = () => { const sanitizedFilePaths: FilePathWithSize[] = [] for (const filePath of filePaths) { const fileStats = await fs.fileStat(filePath, true) - if (!fileStats || fileStats.isDirectory) continue + if (!fileStats) continue - const fileName = await baseName(filePath) - sanitizedFilePaths.push({ - path: filePath, - name: fileName, - size: fileStats.size, - }) + if (!fileStats.isDirectory) { + const fileName = await baseName(filePath) + sanitizedFilePaths.push({ + path: filePath, + name: fileName, + size: fileStats.size, + }) + } else { + // allowing only one level of directory + const files = await fs.readdirSync(filePath) + + for (const file of files) { + const fullPath = await joinPath([filePath, file]) + const fileStats = await fs.fileStat(fullPath, true) + if (!fileStats || fileStats.isDirectory) continue + + sanitizedFilePaths.push({ + path: fullPath, + name: file, + size: fileStats.size, + }) + } + } } const unsupportedFiles = sanitizedFilePaths.filter( @@ -68,7 +85,7 @@ const SelectingModelModal: React.FC = () => { ) if (unsupportedFiles.length > 0) { snackbar({ - description: `File has to be a .gguf file`, + description: `Only files with .gguf extension can be imported.`, type: 'error', }) } From 1bdf7913603d2a39273313fea7a41d1ebe81868b Mon Sep 17 00:00:00 2001 From: Louis Date: Sun, 3 Mar 2024 20:39:38 +0700 Subject: [PATCH 8/9] fix: import from HuggingFace with random string is causing app crash (#2214) --- web/hooks/useGetHFRepoData.ts | 4 +++- .../ExploreModels/HuggingFaceRepoDataLoadedModal/index.tsx | 2 +- .../ExploreModels/HuggingFaceSearchErrorModal/index.tsx | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/web/hooks/useGetHFRepoData.ts b/web/hooks/useGetHFRepoData.ts index 45f979fbd..d14458854 100644 --- a/web/hooks/useGetHFRepoData.ts +++ b/web/hooks/useGetHFRepoData.ts @@ -20,7 +20,9 @@ export const useGetHFRepoData = () => { const data = await res.json() setRepoData(data) } catch (err) { - setFetchError(err as Error) + setFetchError( + Error("The repo does not exist or you don't have access to it.") + ) } setLoading(false) } diff --git a/web/screens/ExploreModels/HuggingFaceRepoDataLoadedModal/index.tsx b/web/screens/ExploreModels/HuggingFaceRepoDataLoadedModal/index.tsx index c4e9131bc..32284ede5 100644 --- a/web/screens/ExploreModels/HuggingFaceRepoDataLoadedModal/index.tsx +++ b/web/screens/ExploreModels/HuggingFaceRepoDataLoadedModal/index.tsx @@ -53,7 +53,7 @@ export const HuggingFaceRepoDataLoadedModal = () => { ? '❌ This model is not supported!' : '✅ This model is supported!'}

- {repoData.tags.includes('gguf') ? ( + {repoData.tags?.includes('gguf') ? (

...But you can import it manually!

) : null}
diff --git a/web/screens/ExploreModels/HuggingFaceSearchErrorModal/index.tsx b/web/screens/ExploreModels/HuggingFaceSearchErrorModal/index.tsx index 31c7d48d4..4cb58332b 100644 --- a/web/screens/ExploreModels/HuggingFaceSearchErrorModal/index.tsx +++ b/web/screens/ExploreModels/HuggingFaceSearchErrorModal/index.tsx @@ -18,7 +18,7 @@ export const HuggingFaceSearchErrorModal = () => {

Error!

Fetch error

-

{fetchError.message}

+

{fetchError.message}