├── javascript ├── .npmrc ├── server │ ├── tsconfig.json │ └── api │ │ ├── models │ │ └── index.ts │ │ └── chat │ │ └── index.ts ├── public │ └── favicon.ico ├── tsconfig.json ├── app.vue ├── nuxt.config.ts ├── app.config.ts ├── components │ ├── Heading.vue │ ├── ModelsDropdown.vue │ ├── Download.vue │ ├── Chat.vue │ └── Models.vue ├── tailwind.css.ts ├── utils │ └── settings.ts ├── .gitignore ├── pages │ ├── index.vue │ ├── models │ │ └── index.vue │ └── settings │ │ └── index.vue ├── .editorconfig ├── package.json ├── layouts │ └── default.vue └── README.md ├── README.md ├── python ├── pyproject.toml └── app.py └── LICENSE /javascript/.npmrc: -------------------------------------------------------------------------------- 1 | shamefully-hoist=true -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Ollama Python & Javascript Libraries Example 2 | -------------------------------------------------------------------------------- /javascript/server/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../.nuxt/tsconfig.server.json" 3 | } 4 | -------------------------------------------------------------------------------- /javascript/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sugarforever/ollama-libraries-example/main/javascript/public/favicon.ico -------------------------------------------------------------------------------- /javascript/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | // https://nuxt.com/docs/guide/concepts/typescript 3 | "extends": "./.nuxt/tsconfig.json" 4 | } 5 | -------------------------------------------------------------------------------- /javascript/app.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /javascript/nuxt.config.ts: -------------------------------------------------------------------------------- 1 | // https://nuxt.com/docs/api/configuration/nuxt-config 2 | export default defineNuxtConfig({ 3 | devtools: { enabled: true }, 4 | modules: ['@nuxt/ui'] 5 | }) 6 | -------------------------------------------------------------------------------- /javascript/server/api/models/index.ts: -------------------------------------------------------------------------------- 1 | import ollama from 'ollama' 2 | 3 | export default defineEventHandler(async (event) => { 4 | const response = await ollama.list(); 5 | return response.models 6 | }) 7 | -------------------------------------------------------------------------------- /javascript/app.config.ts: -------------------------------------------------------------------------------- 1 | export default defineAppConfig({ 2 | ui: { 3 | notifications: { 4 | position: 'top-0 bottom-auto' 5 | }, 6 | primary: 'indigo', 7 | gray: 'cool' 8 | } 9 | }) 10 | -------------------------------------------------------------------------------- /javascript/components/Heading.vue: -------------------------------------------------------------------------------- 1 | 6 | 9 | -------------------------------------------------------------------------------- /javascript/tailwind.css.ts: -------------------------------------------------------------------------------- 1 | import type { Config } from 'tailwindcss' 2 | 3 | export default >{ 4 | theme: { 5 | extend: { 6 | aspectRatio: { 7 | auto: 'auto', 8 | square: '1 / 1', 9 | video: '16 / 9' 10 | } 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /javascript/utils/settings.ts: -------------------------------------------------------------------------------- 1 | const OLLAMA_HOST = 'ollama.host'; 2 | 3 | export const loadOllamaHost = () => { 4 | const host = localStorage.getItem(OLLAMA_HOST); 5 | return host; 6 | } 7 | 8 | export const saveOllamaHost = (host) => { 9 | localStorage.setItem(OLLAMA_HOST, host); 10 | } 11 | -------------------------------------------------------------------------------- /javascript/.gitignore: -------------------------------------------------------------------------------- 1 | # Nuxt dev/build outputs 2 | .output 3 | .data 4 | .nuxt 5 | .nitro 6 | .cache 7 | dist 8 | 9 | # Node dependencies 10 | node_modules 11 | 12 | # Logs 13 | logs 14 | *.log 15 | 16 | # Misc 17 | .DS_Store 18 | .fleet 19 | .idea 20 | 21 | # Local env files 22 | .env 23 | .env.* 24 | !.env.example 25 | -------------------------------------------------------------------------------- /javascript/pages/index.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 18 | -------------------------------------------------------------------------------- /javascript/server/api/chat/index.ts: -------------------------------------------------------------------------------- 1 | import ollama from 'ollama'; 2 | 3 | export default defineEventHandler(async (event) => { 4 | const { model, content } = await readBody(event); 5 | console.log('Model to chat with:', model) 6 | 7 | const message = { role: 'user', content: content }; 8 | const response = await ollama.chat({ model: model, messages: [message], stream: false }); 9 | 10 | return response; 11 | }) 12 | -------------------------------------------------------------------------------- /javascript/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | insert_final_newline = true 7 | indent_style = space 8 | indent_size = 4 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | 14 | [*.{yml,yaml}] 15 | indent_size = 2 16 | 17 | [*.{vue,js,ts}] 18 | indent_style = space 19 | indent_size = 2 20 | 21 | [docker-compose.yml] 22 | indent_size = 4 23 | -------------------------------------------------------------------------------- /javascript/pages/models/index.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 18 | -------------------------------------------------------------------------------- /python/pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "ollama-streamlit" 3 | version = "0.1.0" 4 | description = "" 5 | authors = ["sugarforever "] 6 | readme = "README.md" 7 | 8 | [tool.poetry.dependencies] 9 | python = "^3.11" 10 | streamlit = "^1.30.0" 11 | ollama = "^0.1.4" 12 | openai = "^1.10.0" 13 | langchain = "^0.1.5" 14 | langchain-community = "^0.0.17" 15 | python-dotenv = "^1.0.1" 16 | 17 | 18 | [build-system] 19 | requires = ["poetry-core"] 20 | build-backend = "poetry.core.masonry.api" 21 | -------------------------------------------------------------------------------- /javascript/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nuxt-app", 3 | "private": true, 4 | "type": "module", 5 | "scripts": { 6 | "build": "nuxt build", 7 | "dev": "nuxt dev", 8 | "generate": "nuxt generate", 9 | "preview": "nuxt preview", 10 | "postinstall": "nuxt prepare" 11 | }, 12 | "devDependencies": { 13 | "@types/ws": "^8.5.10", 14 | "nuxt": "^3.10.0", 15 | "vue": "^3.4.15", 16 | "vue-router": "^4.2.5" 17 | }, 18 | "dependencies": { 19 | "@nuxt/ui": "^2.13.0", 20 | "ai": "^2.2.33", 21 | "ollama": "^0.4.5", 22 | "openai": "^4.26.1", 23 | "ws": "^8.16.0" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /javascript/layouts/default.vue: -------------------------------------------------------------------------------- 1 | 23 | 33 | -------------------------------------------------------------------------------- /javascript/README.md: -------------------------------------------------------------------------------- 1 | # Chat Ollama 2 | 3 | This is a Nuxt 3 + Ollama web application. It's an example of Ollama Javascript library. 4 | 5 | Feature list: 6 | - Models management (list, download, delete) 7 | - Chat with models 8 | 9 | ## Setup 10 | 11 | Make sure to install the dependencies: 12 | 13 | ```bash 14 | # npm 15 | npm install 16 | 17 | # pnpm 18 | pnpm install 19 | 20 | # yarn 21 | yarn install 22 | 23 | # bun 24 | bun install 25 | ``` 26 | 27 | ## Ollama Server 28 | 29 | You will need an Ollama server running. You can run it in local environment following the installation guide of [Ollama](https://github.com/ollama/ollama). 30 | 31 | By default, Ollama server is running on http://localhost:11434. 32 | 33 | ## Development Server 34 | 35 | Start the development server on `http://localhost:3000`: 36 | 37 | ```bash 38 | # npm 39 | npm run dev 40 | 41 | # pnpm 42 | pnpm run dev 43 | 44 | # yarn 45 | yarn dev 46 | 47 | # bun 48 | bun run dev 49 | ``` 50 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 sugarforever 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /javascript/components/ModelsDropdown.vue: -------------------------------------------------------------------------------- 1 | 31 | 38 | -------------------------------------------------------------------------------- /javascript/pages/settings/index.vue: -------------------------------------------------------------------------------- 1 | 42 | 43 | 57 | -------------------------------------------------------------------------------- /python/app.py: -------------------------------------------------------------------------------- 1 | import streamlit as st 2 | import ollama 3 | 4 | model_list = ollama.list() 5 | 6 | if "model_name" not in st.session_state: 7 | st.session_state["model_name"] = "llama2:7b-chat" 8 | 9 | if "messages" not in st.session_state: 10 | st.session_state.messages = [] 11 | 12 | with st.sidebar: 13 | st.subheader("Settings") 14 | 15 | option = st.selectbox( 16 | 'Select a model', 17 | [model['name'] for model in model_list['models']]) 18 | st.write('You selected:', option) 19 | st.session_state["model_name"] = option 20 | 21 | st.title(f"Chat with {st.session_state['model_name']}") 22 | 23 | for message in st.session_state.messages: 24 | with st.chat_message(message["role"]): 25 | st.markdown(message["content"]) 26 | 27 | if prompt := st.chat_input("What is up?"): 28 | 29 | st.session_state.messages.append({"role": "user", "content": prompt}) 30 | 31 | with st.chat_message("user"): 32 | st.markdown(prompt) 33 | 34 | with st.chat_message("assistant"): 35 | message_placeholder = st.empty() 36 | full_response = "" 37 | for chunk in ollama.chat( 38 | model=st.session_state["model_name"], 39 | messages=[ 40 | {"role": m["role"], "content": m["content"]} 41 | for m in st.session_state.messages 42 | ], 43 | stream=True, 44 | ): 45 | if 'message' in chunk and 'content' in chunk['message']: 46 | full_response += (chunk['message']['content'] or "") 47 | message_placeholder.markdown(full_response + "▌") 48 | message_placeholder.markdown(full_response) 49 | st.session_state.messages.append({"role": "assistant", "content": full_response}) -------------------------------------------------------------------------------- /javascript/components/Download.vue: -------------------------------------------------------------------------------- 1 | 44 | 45 | 68 | -------------------------------------------------------------------------------- /javascript/components/Chat.vue: -------------------------------------------------------------------------------- 1 | 71 | 103 | -------------------------------------------------------------------------------- /javascript/components/Models.vue: -------------------------------------------------------------------------------- 1 | 118 | 119 | 163 | --------------------------------------------------------------------------------