Download install_functions..py from Nerdur/webui: direct link, hf CLI and curl.
- Browser
- Download file 18.5 kB
-
https://huggingface.co/spaces/Nerdur/webui/resolve/main/install_functions..py
- Command line
-
hf download hf://spaces/Nerdur/webui/install_functions..py
-
curl -L -o install_functions..py https://huggingface.co/spaces/Nerdur/webui/resolve/main/install_functions..py
18.5 kB
| """ | |
| Instalira sve funkcije (filters, tools, actions) i kreira Custom Model Preset. | |
| Poziva se automatski iz setup_endpoints.sh pri startu Space-a. | |
| Koristi: python3 install_functions.py <base_url> <token> | |
| """ | |
| import json | |
| import urllib.request | |
| import urllib.error | |
| import sys | |
| import os | |
| BASE_URL = sys.argv[1] if len(sys.argv) > 1 else 'http://localhost:8080' | |
| TOKEN = sys.argv[2] if len(sys.argv) > 2 else '' | |
| if not TOKEN: | |
| print("β No token provided.") | |
| sys.exit(1) | |
| HEADERS = { | |
| 'Content-Type': 'application/json', | |
| 'Authorization': f'Bearer {TOKEN}' | |
| } | |
| APP_DIR = os.path.dirname(os.path.abspath(__file__)) | |
| # βββββββββββββββββββββββββββββββββββββββββββββ | |
| # Helpers | |
| # βββββββββββββββββββββββββββββββββββββββββββββ | |
| def api(method, path, data=None): | |
| url = BASE_URL + path | |
| body = json.dumps(data).encode() if data is not None else None | |
| req = urllib.request.Request(url, data=body, headers=HEADERS, method=method) | |
| try: | |
| with urllib.request.urlopen(req) as r: | |
| return r.status, json.loads(r.read().decode()) | |
| except urllib.error.HTTPError as e: | |
| return e.code, e.read().decode() | |
| def install_function(func_id, name, func_type, content): | |
| """Instaliraj ili aΕΎuriraj funkciju.""" | |
| # Provjeri postoji li | |
| status, _ = api('GET', f'/api/v1/functions/id/{func_id}') | |
| payload = { | |
| 'id': func_id, | |
| 'name': name, | |
| 'type': func_type, | |
| 'content': content, | |
| 'meta': {'description': name} | |
| } | |
| if status == 200: | |
| s, r = api('POST', f'/api/v1/functions/id/{func_id}/update', payload) | |
| label = "aΕΎuriran" if s == 200 else f"greΕ‘ka {s}" | |
| else: | |
| s, r = api('POST', '/api/v1/functions/create', payload) | |
| label = "instaliran" if s == 200 else f"greΕ‘ka {s}" | |
| # Aktiviraj | |
| api('POST', f'/api/v1/functions/id/{func_id}/toggle') | |
| icon = "β " if s == 200 else "β" | |
| print(f" {icon} [{func_type}] {name} β {label}") | |
| return s == 200 | |
| def load_json_function(filepath): | |
| """UΔitaj funkciju iz JSON export fajla.""" | |
| with open(filepath) as f: | |
| d = json.load(f) | |
| item = d[0] if isinstance(d, list) else d | |
| # Detektuj tip iz sadrΕΎaja | |
| content = item.get('content', '') | |
| if 'class Filter' in content: | |
| ftype = 'filter' | |
| elif 'class Pipe' in content: | |
| ftype = 'pipe' | |
| elif 'class Tools' in content or 'class Action' in content: | |
| ftype = 'action' | |
| else: | |
| ftype = item.get('meta', {}).get('type', 'filter') | |
| return item['id'], item['name'], ftype, content | |
| # βββββββββββββββββββββββββββββββββββββββββββββ | |
| # 1. Instaliraj sve JSON funkcije | |
| # βββββββββββββββββββββββββββββββββββββββββββββ | |
| print("\nπ¦ Instaliram funkcije iz JSON fajlova...") | |
| JSON_FILES = [ | |
| 'global_system_prompt_filter.json', | |
| '__easysearch_v0_4_3__high-performance_web_search_filter.json', | |
| 'token_saver.json', | |
| 'context_clip_filter.json', | |
| 'auto_disable_native_tools.json', | |
| 'auto_memory.json', | |
| '__mermaid_doctor_-_heals_broken_mermaid_diagrams_generated_by_small_or_hallucinating_models.json', | |
| 'github_simple.json', | |
| 'pdf_tools_-_rich_ui_for_in_context_basic_editing_.json', | |
| ] | |
| installed_filter_ids = [] | |
| for fname in JSON_FILES: | |
| fpath = os.path.join(APP_DIR, fname) | |
| if not os.path.exists(fpath): | |
| print(f" β οΈ {fname} nije pronaΔen, preskaΔem") | |
| continue | |
| func_id, name, ftype, content = load_json_function(fpath) | |
| ok = install_function(func_id, name, ftype, content) | |
| if ok and ftype == 'filter': | |
| installed_filter_ids.append(func_id) | |
| # βββββββββββββββββββββββββββββββββββββββββββββ | |
| # 2. Instaliraj naΕ‘e custom Python funkcije | |
| # βββββββββββββββββββββββββββββββββββββββββββββ | |
| print("\nπ οΈ Instaliram custom funkcije...") | |
| CUSTOM_FUNCTIONS = [ | |
| ('context_detector', 'Context Detector', 'filter', 'context_detector.py'), | |
| ('token_compressor', 'Token Compressor', 'filter', 'token_compressor.py'), | |
| ('coding_fallback', 'π Smart Coding Router', 'pipe', 'coding_priority_pipe.py'), | |
| ('smart_matcher', 'Smart Matcher', 'tool', 'smart_matcher.py'), | |
| ] | |
| for func_id, name, ftype, pyfile in CUSTOM_FUNCTIONS: | |
| fpath = os.path.join(APP_DIR, pyfile) | |
| if not os.path.exists(fpath): | |
| print(f" β οΈ {pyfile} nije pronaΔen") | |
| continue | |
| content = open(fpath).read() | |
| ok = install_function(func_id, name, ftype, content) | |
| if ok and ftype == 'filter': | |
| installed_filter_ids.append(func_id) | |
| # βββββββββββββββββββββββββββββββββββββββββββββ | |
| # 3. Postavi Global System Prompt | |
| # βββββββββββββββββββββββββββββββββββββββββββββ | |
| print("\nπ Postavljam Global System Prompt...") | |
| SYSTEM_PROMPT_FILE = os.path.join(APP_DIR, 'system_prompt.txt') | |
| if os.path.exists(SYSTEM_PROMPT_FILE): | |
| system_prompt = open(SYSTEM_PROMPT_FILE).read() | |
| # Update valve za global_system_prompt_filter | |
| valve_payload = { | |
| 'system_message': system_prompt, | |
| 'timezone': 'Europe/Sarajevo', | |
| 'skip_tags': [] | |
| } | |
| s, r = api('POST', '/api/v1/functions/id/global_system_prompt_filter/valves/update', valve_payload) | |
| if s == 200: | |
| print(" β System prompt postavljen") | |
| else: | |
| print(f" β οΈ GreΕ‘ka pri postavljanju system prompta: {s}") | |
| else: | |
| print(" β οΈ system_prompt.txt nije pronaΔen") | |
| # βββββββββββββββββββββββββββββββββββββββββββββ | |
| # 4. Kreiraj Custom Model Preset | |
| # βββββββββββββββββββββββββββββββββββββββββββββ | |
| print("\nπ€ Kreiram Custom Model Preset...") | |
| # Sve filter ID-ove koji treba biti aktivni na modelu | |
| ALL_FILTER_IDS = list(dict.fromkeys([ | |
| 'global_system_prompt_filter', | |
| 'easysearch', | |
| 'token_saver', | |
| 'context_clip_filter', | |
| 'auto_disable_native_tools', | |
| 'auto_memory', | |
| 'context_detector', | |
| 'token_compressor', | |
| 'mermaid_doctor', | |
| ] + installed_filter_ids)) | |
| model_payload = { | |
| 'id': 'nerdur_assistant', | |
| 'name': 'π§ Nerdur Assistant (Full)', | |
| 'base_model_id': 'coding_fallback.coding_fallback', | |
| 'meta': { | |
| 'description': 'Smart Coding Router sa svim filterima: web search, memory, token saver, context detector i viΕ‘e.', | |
| 'profile_image_url': '/static/favicon.png', | |
| 'tags': [{'name': 'custom'}, {'name': 'coding'}], | |
| 'capabilities': { | |
| 'vision': False, | |
| 'citations': True, | |
| 'usage': True, | |
| } | |
| }, | |
| 'params': { | |
| 'system': open(SYSTEM_PROMPT_FILE).read() if os.path.exists(SYSTEM_PROMPT_FILE) else '', | |
| 'temperature': 0.2, | |
| 'max_tokens': 4096, | |
| }, | |
| 'filter_ids': ALL_FILTER_IDS, | |
| 'tool_ids': ['smart_matcher'], | |
| 'action_ids': ['pdf_tools_rich_ui_editor'], | |
| } | |
| # Provjeri postoji li model | |
| status, _ = api('GET', '/api/v1/models/model?id=nerdur_assistant') | |
| if status == 200: | |
| s, r = api('POST', '/api/v1/models/model/update?id=nerdur_assistant', model_payload) | |
| label = "aΕΎuriran" if s == 200 else f"greΕ‘ka {s}: {str(r)[:100]}" | |
| else: | |
| s, r = api('POST', '/api/v1/models/create', model_payload) | |
| label = "kreiran" if s == 200 else f"greΕ‘ka {s}: {str(r)[:100]}" | |
| icon = "β " if s == 200 else "β" | |
| print(f" {icon} Model 'π§ Nerdur Assistant (Full)' β {label}") | |
| print("\nβ Instalacija zavrΕ‘ena!") | |
| # βββββββββββββββββββββββββββββββββββββββββββββ | |
| # 5. Kreiraj Gemini 2.5 Flash Preset | |
| # βββββββββββββββββββββββββββββββββββββββββββββ | |
| print("\nβ‘ Kreiram Gemini 2.5 Flash Preset...") | |
| gemini_payload = { | |
| 'id': 'nerdur_gemini_flash', | |
| 'name': 'β‘ Gemini 2.5 Flash (Coding)', | |
| 'base_model_id': 'models/gemini-2.5-flash', | |
| 'meta': { | |
| 'description': 'Gemini 2.5 Flash sa svim filterima β web search, memory, token saver i viΕ‘e.', | |
| 'profile_image_url': '/static/favicon.png', | |
| 'tags': [{'name': 'custom'}, {'name': 'coding'}, {'name': 'gemini'}], | |
| 'capabilities': { | |
| 'vision': True, | |
| 'citations': True, | |
| 'usage': True, | |
| } | |
| }, | |
| 'params': { | |
| 'system': open(SYSTEM_PROMPT_FILE).read() if os.path.exists(SYSTEM_PROMPT_FILE) else '', | |
| 'temperature': 0.2, | |
| 'max_tokens': 8192, | |
| }, | |
| 'filter_ids': ALL_FILTER_IDS, | |
| 'tool_ids': ['smart_matcher'], | |
| 'action_ids': ['pdf_tools_rich_ui_editor'], | |
| } | |
| status, _ = api('GET', '/api/v1/models/model?id=nerdur_gemini_flash') | |
| if status == 200: | |
| s, r = api('POST', '/api/v1/models/model/update?id=nerdur_gemini_flash', gemini_payload) | |
| label = "aΕΎuriran" if s == 200 else f"greΕ‘ka {s}: {str(r)[:100]}" | |
| else: | |
| s, r = api('POST', '/api/v1/models/create', gemini_payload) | |
| label = "kreiran" if s == 200 else f"greΕ‘ka {s}: {str(r)[:100]}" | |
| icon = "β " if s == 200 else "β" | |
| print(f" {icon} Model 'β‘ Gemini 2.5 Flash (Coding)' β {label}") | |
| print("\nβ Svi modeli kreirani!") | |
| # βββββββββββββββββββββββββββββββββββββββββββββ | |
| # 6. Groq preset | |
| # βββββββββββββββββββββββββββββββββββββββββββββ | |
| print("\nπ Kreiram Groq preset...") | |
| groq_payload = { | |
| 'id': 'nerdur_groq_coding', | |
| 'name': 'π Groq Llama 3.3 70B (Coding)', | |
| 'base_model_id': 'groq/llama-3.3-70b-versatile', | |
| 'meta': { | |
| 'description': 'Kimi K2 na Groq β izuzetno brz, odliΔan za kodiranje, besplatan.', | |
| 'profile_image_url': '/static/favicon.png', | |
| 'tags': [{'name': 'custom'}, {'name': 'coding'}, {'name': 'groq'}], | |
| 'capabilities': {'vision': False, 'citations': True, 'usage': True} | |
| }, | |
| 'params': { | |
| 'system': open(SYSTEM_PROMPT_FILE).read() if os.path.exists(SYSTEM_PROMPT_FILE) else '', | |
| 'temperature': 0.2, | |
| 'max_tokens': 8192, | |
| }, | |
| 'filter_ids': ALL_FILTER_IDS, | |
| 'tool_ids': ['smart_matcher'], | |
| 'action_ids': ['pdf_tools_rich_ui_editor'], | |
| } | |
| status, _ = api('GET', '/api/v1/models/model?id=nerdur_groq_coding') | |
| if status == 200: | |
| s, r = api('POST', '/api/v1/models/model/update?id=nerdur_groq_coding', groq_payload) | |
| label = "aΕΎuriran" if s == 200 else f"greΕ‘ka {s}: {str(r)[:100]}" | |
| else: | |
| s, r = api('POST', '/api/v1/models/create', groq_payload) | |
| label = "kreiran" if s == 200 else f"greΕ‘ka {s}: {str(r)[:100]}" | |
| print(f" {'β ' if s == 200 else 'β'} 'π Groq Kimi K2 (Coding)' β {label}") | |
| # βββββββββββββββββββββββββββββββββββββββββββββ | |
| # 7. Cerebras preset | |
| # βββββββββββββββββββββββββββββββββββββββββββββ | |
| print("\nπ§ Kreiram Cerebras preset...") | |
| cerebras_payload = { | |
| 'id': 'nerdur_cerebras_coding', | |
| 'name': 'π§ Cerebras Llama 4 Scout (Coding)', | |
| 'base_model_id': 'cerebras/llama-4-scout-17b-16e-instruct', | |
| 'meta': { | |
| 'description': 'Llama 3.3 70B na Cerebras β jedan od najbrΕΎih inference engine-a, besplatan.', | |
| 'profile_image_url': '/static/favicon.png', | |
| 'tags': [{'name': 'custom'}, {'name': 'coding'}, {'name': 'cerebras'}], | |
| 'capabilities': {'vision': False, 'citations': True, 'usage': True} | |
| }, | |
| 'params': { | |
| 'system': open(SYSTEM_PROMPT_FILE).read() if os.path.exists(SYSTEM_PROMPT_FILE) else '', | |
| 'temperature': 0.2, | |
| 'max_tokens': 8192, | |
| }, | |
| 'filter_ids': ALL_FILTER_IDS, | |
| 'tool_ids': ['smart_matcher'], | |
| 'action_ids': ['pdf_tools_rich_ui_editor'], | |
| } | |
| status, _ = api('GET', '/api/v1/models/model?id=nerdur_cerebras_coding') | |
| if status == 200: | |
| s, r = api('POST', '/api/v1/models/model/update?id=nerdur_cerebras_coding', cerebras_payload) | |
| label = "aΕΎuriran" if s == 200 else f"greΕ‘ka {s}: {str(r)[:100]}" | |
| else: | |
| s, r = api('POST', '/api/v1/models/create', cerebras_payload) | |
| label = "kreiran" if s == 200 else f"greΕ‘ka {s}: {str(r)[:100]}" | |
| print(f" {'β ' if s == 200 else 'β'} 'π§ Cerebras Llama 3.3 (Coding)' β {label}") | |
| # βββββββββββββββββββββββββββββββββββββββββββββ | |
| # 8. SambaNova preset | |
| # βββββββββββββββββββββββββββββββββββββββββββββ | |
| print("\nβ‘ Kreiram SambaNova preset...") | |
| sambanova_payload = { | |
| 'id': 'nerdur_sambanova_coding', | |
| 'name': 'β‘ SambaNova Llama 3.3 (Coding)', | |
| 'base_model_id': 'Meta-Llama-3.3-70B-Instruct', | |
| 'meta': { | |
| 'description': 'Llama 3.3 70B na SambaNova β brz inference, dobar za kodiranje, besplatan.', | |
| 'profile_image_url': '/static/favicon.png', | |
| 'tags': [{'name': 'custom'}, {'name': 'coding'}, {'name': 'sambanova'}], | |
| 'capabilities': {'vision': False, 'citations': True, 'usage': True} | |
| }, | |
| 'params': { | |
| 'system': open(SYSTEM_PROMPT_FILE).read() if os.path.exists(SYSTEM_PROMPT_FILE) else '', | |
| 'temperature': 0.2, | |
| 'max_tokens': 8192, | |
| }, | |
| 'filter_ids': ALL_FILTER_IDS, | |
| 'tool_ids': ['smart_matcher'], | |
| 'action_ids': ['pdf_tools_rich_ui_editor'], | |
| } | |
| status, _ = api('GET', '/api/v1/models/model?id=nerdur_sambanova_coding') | |
| if status == 200: | |
| s, r = api('POST', '/api/v1/models/model/update?id=nerdur_sambanova_coding', sambanova_payload) | |
| label = "aΕΎuriran" if s == 200 else f"greΕ‘ka {s}: {str(r)[:100]}" | |
| else: | |
| s, r = api('POST', '/api/v1/models/create', sambanova_payload) | |
| label = "kreiran" if s == 200 else f"greΕ‘ka {s}: {str(r)[:100]}" | |
| print(f" {'β ' if s == 200 else 'β'} 'β‘ SambaNova Llama 3.3 (Coding)' β {label}") | |
| print("\nπ Svih 5 preseta kreirano!") | |
| # βββββββββββββββββββββββββββββββββββββββββββββ | |
| # 9. Dodatni presets za sve aktivne provajdere | |
| # βββββββββββββββββββββββββββββββββββββββββββββ | |
| EXTRA_MODELS = [ | |
| { | |
| 'id': 'nerdur_claude', | |
| 'name': 'π£ Claude Sonnet 4.5 (Coding)', | |
| 'base_model_id': 'anthropic/claude-sonnet-4-5', | |
| 'desc': 'Claude Sonnet 4.5 via Anthropic β odliΔan za kodiranje i analizu.', | |
| 'max_tokens': 8192, | |
| 'vision': True, | |
| }, | |
| { | |
| 'id': 'nerdur_gpt4o', | |
| 'name': 'π’ GPT-4o (Coding)', | |
| 'base_model_id': 'openai/gpt-4o', | |
| 'desc': 'OpenAI GPT-4o β multimodalan, odliΔan za kodiranje.', | |
| 'max_tokens': 4096, | |
| 'vision': True, | |
| }, | |
| { | |
| 'id': 'nerdur_mistral', | |
| 'name': 'π΅ Mistral Large (Coding)', | |
| 'base_model_id': 'mistral-large-latest', | |
| 'desc': 'Mistral Large β odliΔan europski model za kodiranje.', | |
| 'max_tokens': 8192, | |
| 'vision': False, | |
| }, | |
| { | |
| 'id': 'nerdur_deepseek', | |
| 'name': 'π΄ DeepSeek V3 (Coding)', | |
| 'base_model_id': 'deepseek/deepseek-chat', | |
| 'desc': 'DeepSeek V3 β izvrstan za kodiranje, vrlo jeftin.', | |
| 'max_tokens': 8192, | |
| 'vision': False, | |
| }, | |
| { | |
| 'id': 'nerdur_xai', | |
| 'name': 'β‘ Grok 3 (Coding)', | |
| 'base_model_id': 'xai/grok-3', | |
| 'desc': 'xAI Grok 3 β jak model sa web pristupom.', | |
| 'max_tokens': 8192, | |
| 'vision': True, | |
| }, | |
| { | |
| 'id': 'nerdur_openrouter_free', | |
| 'name': 'π OpenRouter Free (Coding)', | |
| 'base_model_id': 'openrouter/meta-llama/llama-4-maverick:free', | |
| 'desc': 'Llama 4 Maverick besplatno via OpenRouter.', | |
| 'max_tokens': 8192, | |
| 'vision': True, | |
| }, | |
| { | |
| 'id': 'nerdur_fireworks', | |
| 'name': 'π₯ Fireworks Llama 4 Scout (Coding)', | |
| 'base_model_id': 'fireworks/accounts/fireworks/models/llama4-scout-instruct-basic', | |
| 'desc': 'Llama 4 Scout na Fireworks β brz i jeftin.', | |
| 'max_tokens': 8192, | |
| 'vision': True, | |
| }, | |
| ] | |
| system_prompt_text = open(SYSTEM_PROMPT_FILE).read() if os.path.exists(SYSTEM_PROMPT_FILE) else '' | |
| print("\nπ Kreiram dodatne provider presete...") | |
| for m in EXTRA_MODELS: | |
| payload = { | |
| 'id': m['id'], | |
| 'name': m['name'], | |
| 'base_model_id': m['base_model_id'], | |
| 'meta': { | |
| 'description': m['desc'], | |
| 'profile_image_url': '/static/favicon.png', | |
| 'tags': [{'name': 'custom'}, {'name': 'coding'}], | |
| 'capabilities': { | |
| 'vision': m['vision'], | |
| 'citations': True, | |
| 'usage': True, | |
| } | |
| }, | |
| 'params': { | |
| 'system': system_prompt_text, | |
| 'temperature': 0.2, | |
| 'max_tokens': m['max_tokens'], | |
| }, | |
| 'filter_ids': ALL_FILTER_IDS, | |
| 'tool_ids': ['smart_matcher'], | |
| 'action_ids': ['pdf_tools_rich_ui_editor'], | |
| } | |
| status, _ = api('GET', f'/api/v1/models/model?id={m["id"]}') | |
| if status == 200: | |
| s, r = api('POST', f'/api/v1/models/model/update?id={m["id"]}', payload) | |
| label = "aΕΎuriran" if s == 200 else f"greΕ‘ka {s}: {str(r)[:80]}" | |
| else: | |
| s, r = api('POST', '/api/v1/models/create', payload) | |
| label = "kreiran" if s == 200 else f"greΕ‘ka {s}: {str(r)[:80]}" | |
| print(f" {'β ' if s == 200 else 'β'} {m['name']} β {label}") | |
| print("\nπ Instalacija kompletna!") | |