11using System ;
22using System . Collections . Generic ;
33using System . Linq ;
4+ using System . Text . Json . Nodes ;
5+ using System . Text . Json ;
46using OpenAI . Models ;
7+ using System . Diagnostics ;
58
69namespace TextForge
710{
@@ -27,136 +30,43 @@ internal class ModelProperties
2730 { "gpt-3.5-turbo-instruct" , 4096 } ,
2831 } ;
2932
30- private static readonly Dictionary < string , int > ollamaModelsContextLength = new Dictionary < string , int > ( )
31- {
32- { "llama3.1" , 131072 } ,
33- { "gemma2" , 8192 } ,
34- { "mistral-nemo" , 1024000 } ,
35- { "mistral-large" , 32768 } ,
36- { "qwen2" , 32768 } ,
37- { "deepseek-coder-v2" , 163840 } ,
38- { "phi3" , 4096 } , // the lowest config of phi3 (https://ollama.com/library/phi3:medium-4k/blobs/0d98d611d31b)
39- { "mistral" , 32768 } ,
40- { "mixtral" , 32768 } ,
41- { "codegemma" , 8192 } ,
42- { "command-r" , 131072 } ,
43- { "command-r-plus" , 131072 } ,
44- { "llava" , 4096 } , // https://ollama.com/library/llava:13b-v1.6-vicuna-q4_0/blobs/87d5b13e5157
45- { "llama3" , 8192 } ,
46- { "gemma" , 8192 } ,
47- { "qwen" , 32768 } ,
48- { "llama2" , 4096 } ,
49- { "codellama" , 16384 } ,
50- { "dolphin-mixtral" , 32768 } ,
51- { "phi" , 2048 } ,
52- { "llama2-uncensored" , 2048 } ,
53- { "deepseek-coder" , 16384 } ,
54- { "dolphin-mistral" , 32768 } ,
55- { "zephyr" , 32768 } ,
56- { "starcoder2" , 16384 } ,
57- { "dolphin-llama3" , 8192 } ,
58- { "orca-mini" , 2048 } ,
59- { "yi" , 4096 } ,
60- { "mistral-openorca" , 32768 } ,
61- { "llava-llama3" , 8192 } ,
62- { "starcoder" , 8192 } ,
63- { "llama2-chinese" , 4096 } ,
64- { "vicuna" , 2048 } , // https://ollama.com/library/vicuna:7b-q3_K_S/blobs/a887a7755a1e
65- { "tinyllama" , 2048 } ,
66- { "codestral" , 32768 } ,
67- { "wizard-vicuna-uncensored" , 2048 } ,
68- { "nous-hermes2" , 4096 } ,
69- { "openchat" , 8192 } ,
70- { "aya" , 8192 } ,
71- { "granite-code" , 2048 } ,
72- { "wizardlm2" , 32768 } ,
73- { "tinydolphin" , 4096 } ,
74- { "wizardcoder" , 16384 } ,
75- { "stable-code" , 16384 } ,
76- { "openhermes" , 32768 } ,
77- { "codeqwen" , 65536 } ,
78- { "codegeex4" , 131072 } ,
79- { "stablelm2" , 4096 } ,
80- { "wizard-math" , 2048 } , // https://ollama.com/library/wizard-math:7b-q5_1/blobs/b39818bfe610
81- { "qwen2-math" , 4096 } ,
82- { "neural-chat" , 32768 } ,
83- { "llama3-gradient" , 1048576 } ,
84- { "phind-codellama" , 16384 } ,
85- { "nous-hermes" , 2048 } , // https://ollama.com/library/nous-hermes:13b-q4_1/blobs/433b4abded9b
86- { "sqlcoder" , 8192 } , // https://ollama.com/library/sqlcoder:15b-q8_0/blobs/2319eec9425f
87- { "dolphincoder" , 16384 } ,
88- { "xwinlm" , 4096 } ,
89- { "deepseek-llm" , 4096 } ,
90- { "yarn-llama2" , 65536 } ,
91- { "llama3-chatqa" , 8192 } ,
92- { "wizardlm" , 2048 } ,
93- { "starling-lm" , 8192 } ,
94- { "falcon" , 2048 } ,
95- { "orca2" , 4096 } ,
96- { "moondream" , 2048 } ,
97- { "samantha-mistral" , 32768 } ,
98- { "solar" , 4096 } ,
99- { "smollm" , 2048 } ,
100- { "stable-beluga" , 4096 } ,
101- { "dolphin-phi" , 2048 } ,
102- { "deepseek-v2" , 163840 } ,
103- { "glm4" , 8192 } , // https://ollama.com/library/glm4:9b-text-q6_K/blobs/2f657a57a8df
104- { "phi3.5" , 131072 } ,
105- { "bakllava" , 32768 } ,
106- { "wizardlm-uncensored" , 4096 } ,
107- { "yarn-mistral" , 32768 } , // https://ollama.com/library/yarn-mistral/blobs/0e8703041ff2
108- { "medllama2" , 4096 } ,
109- { "llama-pro" , 4096 } ,
110- { "llava-phi3" , 4096 } ,
111- { "meditron" , 2048 } ,
112- { "nous-hermes2-mixtral" , 32768 } ,
113- { "nexusraven" , 16384 } ,
114- { "hermes3" , 131072 } ,
115- { "codeup" , 4096 } ,
116- { "everythinglm" , 16384 } ,
117- { "internlm2" , 32768 } ,
118- { "magicoder" , 16384 } ,
119- { "stablelm-zephyr" , 4096 } ,
120- { "codebooga" , 16384 } ,
121- { "yi-coder" , 131072 } ,
122- { "mistrallite" , 32768 } ,
123- { "llama3-groq-tool-use" , 8192 } ,
124- { "falcon2" , 2048 } ,
125- { "wizard-vicuna" , 2048 } ,
126- { "duckdb-nsql" , 16384 } ,
127- { "megadolphin" , 4096 } ,
128- { "reflection" , 8192 } ,
129- { "notux" , 32768 } ,
130- { "goliath" , 4096 } ,
131- { "open-orca-platypus2" , 4096 } ,
132- { "notus" , 32768 } ,
133- { "dbrx" , 32768 } ,
134- { "mathstral" , 32768 } ,
135- { "alfred" , 2048 } ,
136- { "nuextract" , 4096 } ,
137- { "firefunction-v2" , 8192 } ,
138- { "deepseek-v2.5" , 163840 } ,
139- // new models
140- { "minicpm-v" , 32768 } ,
141- { "reader-lm" , 256000 } ,
142- { "mistral-small" , 131072 } ,
143- { "bespoke-minicheck" , 32768 } ,
144- { "qwen2.5" , 32768 } ,
145- { "nemotron-mini" , 4096 } ,
146- { "solar-pro" , 4096 } ,
147- { "qwen2.5-coder" , 32768 }
148- } ;
33+ private static bool IsOllamaEndpoint = false ;
34+ private static bool IsOllamaFetched = false ;
35+ private static Dictionary < string , int > ollamaContextWindowCache = new Dictionary < string , int > ( ) ;
14936
150- public static int GetContextLength ( string modelName )
37+ public static int GetContextLength ( string modelName , OpenAIModelCollection availableModels )
15138 {
15239 if ( openAIModelsContextLength . ContainsKey ( modelName ) )
15340 {
15441 return openAIModelsContextLength [ modelName ] ;
15542 }
15643 else if ( modelName . Contains ( ':' ) )
15744 {
158- string key = modelName . Split ( ':' ) [ 0 ] ;
159- return ollamaModelsContextLength . ContainsKey ( key ) ? ollamaModelsContextLength [ key ] : BaselineContextWindowLength ;
45+ try
46+ {
47+ if ( ! IsOllamaFetched )
48+ {
49+ IsOllamaEndpoint = IsOllama ( availableModels ) ;
50+ IsOllamaFetched = true ;
51+ }
52+ if ( IsOllamaEndpoint )
53+ {
54+ int contextWindow ;
55+ if ( ! ollamaContextWindowCache . TryGetValue ( modelName , out contextWindow ) )
56+ {
57+ contextWindow = GetOllamaModelContextWindow ( modelName ) ;
58+ ollamaContextWindowCache [ modelName ] = contextWindow ;
59+ }
60+ return contextWindow ;
61+ } else
62+ {
63+ return BaselineContextWindowLength ;
64+ }
65+ } catch ( OllamaMissingContextWindowException ex )
66+ {
67+ CommonUtils . DisplayWarning ( ex ) ;
68+ return BaselineContextWindowLength ;
69+ }
16070 }
16171 else if ( modelName . StartsWith ( "o1" ) )
16272 {
@@ -184,10 +94,44 @@ public static int GetContextLength(string modelName)
18494 }
18595 }
18696
187- public static IEnumerable < string > GetModelList ( ModelClient client )
97+ public static IEnumerable < string > GetModelList ( OpenAIModelCollection availableModels )
18898 {
189- OpenAIModelInfoCollection availableModels = client . GetModels ( ) . Value ;
19099 return availableModels . Select ( info => info . Id ) . ToList ( ) ;
191100 }
101+
102+ private static bool IsOllama ( OpenAIModelCollection availableModels )
103+ {
104+ return ( availableModels . Count == 0 ) ? false : availableModels . First ( ) . OwnedBy == "library" ;
105+ }
106+
107+ private static int GetOllamaModelContextWindow ( string model )
108+ {
109+ var ollamaEndpoint = ThisAddIn . OpenAIEndpoint . Replace ( "/v1" , "" ) ;
110+
111+ Ollama ollamaInstance = new Ollama ( new Uri ( ollamaEndpoint ) ) ;
112+ var dict = ollamaInstance . Show ( model , true ) . Result ; // or await, if Show() is async
113+
114+ // Navigate to "model_info"
115+ if ( dict . TryGetValue ( "model_info" , out var modelInfoObj ) && modelInfoObj is JsonElement modelInfoElement )
116+ {
117+ // Use JsonNode or JsonElement to search for "context_length" key
118+ var modelInfoNode = JsonNode . Parse ( modelInfoElement . GetRawText ( ) ) ;
119+
120+ foreach ( var keyValuePair in modelInfoNode . AsObject ( ) )
121+ {
122+ // Search for a nested object containing "context_length"
123+ if ( keyValuePair . Key . EndsWith ( ".context_length" ) )
124+ {
125+ return int . Parse ( keyValuePair . Value . ToString ( ) ) ;
126+ }
127+ }
128+ }
129+ throw new OllamaMissingContextWindowException ( $ "Unable to fetch the context length for { model } !") ;
130+ }
131+ }
132+
133+ public class OllamaMissingContextWindowException : ApplicationException
134+ {
135+ public OllamaMissingContextWindowException ( string message ) : base ( message ) { }
192136 }
193137}
0 commit comments