Skip to content

Commit 1ec2f5c

Browse files
authored
Merge pull request #185 from Arkissa/feat/AiClient
feat: 为 rhythm 支持 AIClient 的功能。
2 parents 84d7551 + 991a586 commit 1ec2f5c

File tree

7 files changed

+513
-0
lines changed

7 files changed

+513
-0
lines changed
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
/*
2+
* Rhythm - A modern community (forum/BBS/SNS/blog) platform written in Java.
3+
* Modified version from Symphony, Thanks Symphony :)
4+
* Copyright (C) 2012-present, b3log.org
5+
*
6+
* This program is free software: you can redistribute it and/or modify
7+
* it under the terms of the GNU Affero General Public License as published by
8+
* the Free Software Foundation, either version 3 of the License, or
9+
* (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU Affero General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Affero General Public License
17+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
18+
*/
19+
package org.b3log.symphony.ai;
20+
21+
import java.io.BufferedReader;
22+
import java.io.IOException;
23+
import java.io.InputStream;
24+
import java.io.InputStreamReader;
25+
import java.net.http.HttpClient;
26+
import java.net.http.HttpResponse;
27+
import java.nio.charset.StandardCharsets;
28+
import java.util.Objects;
29+
import java.util.function.Supplier;
30+
import java.util.stream.Stream;
31+
32+
import org.json.JSONObject;
33+
import org.json.JSONException;
34+
35+
public class AIClient {
36+
private HttpClient client;
37+
38+
public AIClient(HttpClient client) {
39+
this.client = client;
40+
}
41+
42+
private class SSE implements Supplier<JSONObject> {
43+
private BufferedReader reader;
44+
private boolean closed = false;
45+
private static String DONE = "data: [DONE]";
46+
47+
public SSE(InputStream inputStream) {
48+
this.reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
49+
}
50+
51+
@Override
52+
public JSONObject get() {
53+
try {
54+
String line;
55+
do {
56+
line = reader.readLine();
57+
if (line == null || line.equals(SSE.DONE)) {
58+
this.reader.close();
59+
this.closed = true;
60+
61+
return null;
62+
}
63+
} while (line.isBlank());
64+
65+
66+
return new JSONObject(line.substring(6));
67+
} catch (IOException | JSONException e) {
68+
if (!this.closed) {
69+
try {
70+
this.reader.close();
71+
} catch (IOException ignore) {}
72+
}
73+
this.closed = true;
74+
75+
return null;
76+
}
77+
}
78+
}
79+
80+
private class Text implements Supplier<JSONObject> {
81+
private BufferedReader reader;
82+
private boolean closed = false;
83+
84+
public Text(InputStream inputStream) {
85+
this.reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
86+
}
87+
88+
@Override
89+
public JSONObject get() {
90+
try {
91+
var line = reader.readAllAsString();
92+
this.reader.close();
93+
this.closed = true;
94+
if (line == null) {
95+
return null;
96+
}
97+
98+
return new JSONObject(line);
99+
} catch (IOException | JSONException e) {
100+
if (!this.closed) {
101+
try {
102+
this.reader.close();
103+
} catch (IOException ignore) {}
104+
}
105+
this.closed = true;
106+
107+
return null;
108+
}
109+
}
110+
}
111+
112+
public Stream<JSONObject> send(Provider provider) throws IOException, InterruptedException, JSONException {
113+
var response = this.client.send(provider.getHttpRequest(), HttpResponse.BodyHandlers.ofInputStream());
114+
var contentType = response.headers().firstValue("Content-Type").orElse("");
115+
var handler = contentType.contains("event-stream")
116+
? new SSE(response.body())
117+
: new Text(response.body());
118+
return Stream.generate(handler).takeWhile(Objects::nonNull);
119+
}
120+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Rhythm - A modern community (forum/BBS/SNS/blog) platform written in Java.
3+
* Modified version from Symphony, Thanks Symphony :)
4+
* Copyright (C) 2012-present, b3log.org
5+
*
6+
* This program is free software: you can redistribute it and/or modify
7+
* it under the terms of the GNU Affero General Public License as published by
8+
* the Free Software Foundation, either version 3 of the License, or
9+
* (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU Affero General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Affero General Public License
17+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
18+
*/
19+
package org.b3log.symphony.ai;
20+
21+
public interface Model {
22+
String getName();
23+
24+
sealed interface Supported permits Supported.Text, Supported.Image {
25+
non-sealed interface Text extends Model, Supported {}
26+
non-sealed interface Image extends Model, Supported {}
27+
}
28+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Rhythm - A modern community (forum/BBS/SNS/blog) platform written in Java.
3+
* Modified version from Symphony, Thanks Symphony :)
4+
* Copyright (C) 2012-present, b3log.org
5+
*
6+
* This program is free software: you can redistribute it and/or modify
7+
* it under the terms of the GNU Affero General Public License as published by
8+
* the Free Software Foundation, either version 3 of the License, or
9+
* (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU Affero General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Affero General Public License
17+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
18+
*/
19+
package org.b3log.symphony.ai;
20+
21+
class ModelNotSupportException extends Exception {
22+
private String type;
23+
private Model model;
24+
25+
ModelNotSupportException(Model model, String type) {
26+
this.type = type;
27+
this.model = model;
28+
}
29+
30+
@Override
31+
public String toString() {
32+
return String.format("Model %s not support this %s content type", this.model.getName(), type);
33+
}
34+
}

0 commit comments

Comments
 (0)