Skip to content
This repository was archived by the owner on Jul 4, 2025. It is now read-only.

Commit 61c3ee1

Browse files
authored
feat: add assistants (#1770)
* feat: add assistants * add pagination messages * allow edit content of message
1 parent a49054c commit 61c3ee1

18 files changed

+813
-38
lines changed

engine/common/assistant.h

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
#pragma once
2+
3+
#include <string>
4+
#include "common/assistant_tool.h"
5+
#include "common/thread_tool_resources.h"
6+
#include "common/variant_map.h"
7+
#include "utils/result.hpp"
8+
9+
namespace OpenAi {
10+
// Deprecated. After jan's migration, we should remove this struct
11+
struct JanAssistant : JsonSerializable {
12+
std::string id;
13+
14+
std::string name;
15+
16+
std::string object = "assistant";
17+
18+
uint32_t created_at;
19+
20+
Json::Value tools;
21+
22+
Json::Value model;
23+
24+
std::string instructions;
25+
26+
~JanAssistant() = default;
27+
28+
cpp::result<Json::Value, std::string> ToJson() override {
29+
try {
30+
Json::Value json;
31+
32+
json["id"] = id;
33+
json["name"] = name;
34+
json["object"] = object;
35+
json["created_at"] = created_at;
36+
37+
json["tools"] = tools;
38+
json["model"] = model;
39+
json["instructions"] = instructions;
40+
41+
return json;
42+
} catch (const std::exception& e) {
43+
return cpp::fail(std::string("ToJson failed: ") + e.what());
44+
}
45+
}
46+
47+
static cpp::result<JanAssistant, std::string> FromJson(Json::Value&& json) {
48+
if (json.empty()) {
49+
return cpp::fail("Empty JSON");
50+
}
51+
52+
JanAssistant assistant;
53+
if (json.isMember("assistant_id")) {
54+
assistant.id = json["assistant_id"].asString();
55+
} else {
56+
assistant.id = json["id"].asString();
57+
}
58+
59+
if (json.isMember("assistant_name")) {
60+
assistant.name = json["assistant_name"].asString();
61+
} else {
62+
assistant.name = json["name"].asString();
63+
}
64+
assistant.object = "assistant";
65+
assistant.created_at = 0; // Jan does not have this
66+
if (json.isMember("tools")) {
67+
assistant.tools = json["tools"];
68+
}
69+
if (json.isMember("model")) {
70+
assistant.model = json["model"];
71+
}
72+
assistant.instructions = json["instructions"].asString();
73+
74+
return assistant;
75+
}
76+
};
77+
78+
struct Assistant {
79+
/**
80+
* The identifier, which can be referenced in API endpoints.
81+
*/
82+
std::string id;
83+
84+
/**
85+
* The object type, which is always assistant.
86+
*/
87+
std::string object = "assistant";
88+
89+
/**
90+
* The Unix timestamp (in seconds) for when the assistant was created.
91+
*/
92+
uint64_t created_at;
93+
94+
/**
95+
* The name of the assistant. The maximum length is 256 characters.
96+
*/
97+
std::optional<std::string> name;
98+
99+
/**
100+
* The description of the assistant. The maximum length is 512 characters.
101+
*/
102+
std::optional<std::string> description;
103+
104+
/**
105+
* ID of the model to use. You can use the List models API to see all of
106+
* your available models, or see our Model overview for descriptions of them.
107+
*/
108+
std::string model;
109+
110+
/**
111+
* The system instructions that the assistant uses. The maximum length is
112+
* 256,000 characters.
113+
*/
114+
std::optional<std::string> instructions;
115+
116+
/**
117+
* A list of tool enabled on the assistant. There can be a maximum of 128
118+
* tools per assistant. Tools can be of types code_interpreter, file_search,
119+
* or function.
120+
*/
121+
std::vector<std::unique_ptr<AssistantTool>> tools;
122+
123+
/**
124+
* A set of resources that are used by the assistant's tools. The resources
125+
* are specific to the type of tool. For example, the code_interpreter tool
126+
* requires a list of file IDs, while the file_search tool requires a list
127+
* of vector store IDs.
128+
*/
129+
std::optional<std::variant<ThreadCodeInterpreter, ThreadFileSearch>>
130+
tool_resources;
131+
132+
/**
133+
* Set of 16 key-value pairs that can be attached to an object. This can be
134+
* useful for storing additional information about the object in a structured
135+
* format. Keys can be a maximum of 64 characters long and values can be a
136+
* maximum of 512 characters long.
137+
*/
138+
Cortex::VariantMap metadata;
139+
140+
/**
141+
* What sampling temperature to use, between 0 and 2. Higher values like
142+
* 0.8 will make the output more random, while lower values like 0.2 will
143+
* make it more focused and deterministic.
144+
*/
145+
std::optional<float> temperature;
146+
147+
/**
148+
* An alternative to sampling with temperature, called nucleus sampling,
149+
* where the model considers the results of the tokens with top_p
150+
* probability mass. So 0.1 means only the tokens comprising the top 10%
151+
* probability mass are considered.
152+
*
153+
* We generally recommend altering this or temperature but not both.
154+
*/
155+
std::optional<float> top_p;
156+
};
157+
} // namespace OpenAi

engine/common/assistant_tool.h

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
#pragma once
2+
3+
#include <optional>
4+
#include <string>
5+
6+
namespace OpenAi {
7+
struct AssistantTool {
8+
std::string type;
9+
10+
AssistantTool(const std::string& type) : type{type} {}
11+
12+
virtual ~AssistantTool() = default;
13+
};
14+
15+
struct AssistantCodeInterpreterTool : public AssistantTool {
16+
AssistantCodeInterpreterTool() : AssistantTool{"code_interpreter"} {}
17+
18+
~AssistantCodeInterpreterTool() = default;
19+
};
20+
21+
struct AssistantFileSearchTool : public AssistantTool {
22+
AssistantFileSearchTool() : AssistantTool("file_search") {}
23+
24+
~AssistantFileSearchTool() = default;
25+
26+
/**
27+
* The ranking options for the file search. If not specified,
28+
* the file search tool will use the auto ranker and a score_threshold of 0.
29+
*
30+
* See the file search tool documentation for more information.
31+
*/
32+
struct RankingOption {
33+
/**
34+
* The ranker to use for the file search. If not specified will use the auto ranker.
35+
*/
36+
std::string ranker;
37+
38+
/**
39+
* The score threshold for the file search. All values must be a
40+
* floating point number between 0 and 1.
41+
*/
42+
float score_threshold;
43+
};
44+
45+
/**
46+
* Overrides for the file search tool.
47+
*/
48+
struct FileSearch {
49+
/**
50+
* The maximum number of results the file search tool should output.
51+
* The default is 20 for gpt-4* models and 5 for gpt-3.5-turbo.
52+
* This number should be between 1 and 50 inclusive.
53+
*
54+
* Note that the file search tool may output fewer than max_num_results results.
55+
* See the file search tool documentation for more information.
56+
*/
57+
int max_num_result;
58+
};
59+
};
60+
61+
struct AssistantFunctionTool : public AssistantTool {
62+
AssistantFunctionTool() : AssistantTool("function") {}
63+
64+
~AssistantFunctionTool() = default;
65+
66+
struct Function {
67+
/**
68+
* A description of what the function does, used by the model to choose
69+
* when and how to call the function.
70+
*/
71+
std::string description;
72+
73+
/**
74+
* The name of the function to be called. Must be a-z, A-Z, 0-9, or contain
75+
* underscores and dashes, with a maximum length of 64.
76+
*/
77+
std::string name;
78+
79+
// TODO: namh handle parameters
80+
81+
/**
82+
* Whether to enable strict schema adherence when generating the function call.
83+
* If set to true, the model will follow the exact schema defined in the parameters
84+
* field. Only a subset of JSON Schema is supported when strict is true.
85+
*
86+
* Learn more about Structured Outputs in the function calling guide.
87+
*/
88+
std::optional<bool> strict;
89+
};
90+
};
91+
} // namespace OpenAi

engine/common/thread.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <json/reader.h>
44
#include <json/value.h>
55
#include <json/writer.h>
6+
#include "common/assistant.h"
67
#include "common/thread_tool_resources.h"
78
#include "common/variant_map.h"
89
#include "json_serializable.h"
@@ -47,6 +48,9 @@ struct Thread : JsonSerializable {
4748
*/
4849
Cortex::VariantMap metadata;
4950

51+
// For supporting Jan
52+
std::optional<std::vector<JanAssistant>> assistants;
53+
5054
static cpp::result<Thread, std::string> FromJson(const Json::Value& json) {
5155
Thread thread;
5256

@@ -90,6 +94,25 @@ struct Thread : JsonSerializable {
9094
}
9195
}
9296

97+
if (json.isMember("title") && !json["title"].isNull()) {
98+
thread.metadata["title"] = json["title"].asString();
99+
}
100+
101+
if (json.isMember("assistants") && json["assistants"].isArray()) {
102+
std::vector<JanAssistant> assistants;
103+
for (Json::ArrayIndex i = 0; i < json["assistants"].size(); ++i) {
104+
Json::Value assistant_json = json["assistants"][i];
105+
auto assistant_result =
106+
JanAssistant::FromJson(std::move(assistant_json));
107+
if (assistant_result.has_error()) {
108+
return cpp::fail("Failed to parse assistant: " +
109+
assistant_result.error());
110+
}
111+
assistants.push_back(std::move(assistant_result.value()));
112+
}
113+
thread.assistants = std::move(assistants);
114+
}
115+
93116
return thread;
94117
}
95118

engine/config/model_config.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,15 @@
11
#pragma once
22

33
#include <json/json.h>
4-
#include <cmath>
54
#include <ctime>
65
#include <fstream>
7-
#include <iomanip>
86
#include <limits>
97
#include <sstream>
108
#include <stdexcept>
119
#include <string>
1210
#include <vector>
1311
#include "utils/format_utils.h"
1412
#include "utils/remote_models_utils.h"
15-
#include "yaml-cpp/yaml.h"
1613

1714
namespace config {
1815

0 commit comments

Comments
 (0)