Repository navigation
Expand file tree
/
Copy pathinference.h
More file actions
111 lines (88 loc) · 3.94 KB
/
Copy pathinference.h
File metadata and controls
111 lines (88 loc) · 3.94 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
/**
* Inference client for OpenAI-compatible APIs
*
* Supports multi-endpoint routing via glob patterns.
* Uses libcurl for HTTP (blocking + streaming SSE).
*/
#pragma once
#include <string>
#include <vector>
#include <map>
#include <functional>
namespace ragger {
/// Chat message
struct Message {
std::string role; // "system", "user", "assistant"
std::string content;
};
/// One inference endpoint with its URL, key, and model glob patterns
struct Endpoint {
std::string name;
std::string api_url;
std::string api_key;
std::string models; // comma-separated glob patterns
std::string format_name; // API format name (openai, anthropic, etc.)
int max_tokens = 0; // 0 = use client default
Endpoint(const std::string& name_,
const std::string& api_url_,
const std::string& api_key_ = "",
const std::string& models_ = "*",
const std::string& format_ = "",
int max_tokens_ = 0);
/// Check if this endpoint handles the given model name (fnmatch-style glob)
bool matches(const std::string& model) const;
/// Check if endpoint is reachable (GET /models or /health, 3s timeout)
bool is_reachable() const;
/// True if endpoint appears to be a local/non-commercial engine
bool is_local() const;
/// Query available models from endpoint (GET /v1/models)
std::vector<std::string> list_models() const;
/// One model entry from LM Studio's authoritative type-tagged listing.
struct TypedModel {
std::string id;
std::string type; // "llm", "embeddings", "vlm", etc. (LM Studio's own classification)
};
/// Query LM Studio's native REST API (GET {base}/api/v0/models), which
/// tags each model with an authoritative "type" field ("llm" /
/// "embeddings" / "vlm") — unlike the OpenAI-compatible /v1/models,
/// which LM Studio (like llama.cpp/Ollama/vLLM) does not annotate.
/// Returns empty on any failure (wrong port, not LM Studio, old LM
/// Studio version, network error) — callers must treat that as "unknown,
/// fall back to name-based heuristics" and NOT as "no models available".
/// Scoped to LM Studio only; other backends should keep using
/// list_models() + keyword heuristics.
std::vector<TypedModel> list_models_lmstudio_typed() const;
};
/// Multi-endpoint inference client
class InferenceClient {
public:
std::string model;
std::string memory_model; // [inference.memory] model, or = model
int max_tokens;
std::vector<Endpoint> endpoints;
InferenceClient(const std::vector<Endpoint>& endpoints,
const std::string& model = "",
int max_tokens = 4096);
/// Build from config
static InferenceClient from_config(const struct Config& cfg);
/// Blocking chat (returns full response text)
std::string chat(const std::vector<Message>& messages,
const std::string& model = "");
/// Blocking chat using the memory model (summarization / routing).
std::string chat_memory(const std::vector<Message>& messages);
/// Ensure model is loaded in local inference engine (e.g. LM Studio).
/// Returns empty string if loaded/not applicable, error message otherwise.
std::string ensure_model_loaded(const std::string& model = "");
/// Force a specific endpoint by name (empty = auto-route)
void set_forced_endpoint(const std::string& name);
/// Set directory for raw payload dumps (empty = disabled)
void set_payload_dump_dir(const std::string& dir) { payload_dump_dir_ = dir; }
/// Get the currently forced endpoint name (empty = auto)
const std::string& forced_endpoint() const { return forced_endpoint_; }
/// Resolve which endpoint handles a given model name
Endpoint& resolve_endpoint(const std::string& model);
private:
std::string forced_endpoint_;
std::string payload_dump_dir_; // if set, write raw request JSON here
};
} // namespace ragger