-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Create assistant chat usecase and repositories (#87)
- Loading branch information
1 parent
58a11e1
commit 92dfb0f
Showing
16 changed files
with
451 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,2 @@ | ||
versionName=6.2.3 | ||
versionCode=2024091519 | ||
versionName=6.2.6 | ||
versionCode=2024122601 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -44,9 +44,6 @@ class CompositeExpertRepositoryImpl implements CompositeExpertRepository { | |
} | ||
return; | ||
} | ||
|
||
|
||
|
||
} | ||
|
||
|
88 changes: 88 additions & 0 deletions
88
packages/data/lib/repositories/assistant_repository_impl.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
import 'dart:convert'; | ||
import 'dart:io'; | ||
|
||
import 'package:domain/entities/assistant.dart'; | ||
import 'package:domain/entities/thread.dart'; | ||
import 'package:http/http.dart' as http; | ||
|
||
import 'package:domain/repositories_abstract/assistant_repository.dart'; | ||
|
||
import '../utils/api_constants.dart'; | ||
|
||
class AssistantRepositoryImp implements AssistantRepository { | ||
final http.Client client; | ||
|
||
AssistantRepositoryImp( | ||
{required this.client}); | ||
|
||
@override | ||
Future<Assistant> createCompositeAssistant() async { | ||
final request = | ||
http.Request('POST', Uri.parse(ApiConstants.assistantsEndpoint)) | ||
..headers.addAll({ | ||
'Content-Type': 'application/json', | ||
'Authorization': 'Bearer ${ApiConstants.apiKey}', | ||
'OpenAI-Beta': 'assistants=v2', | ||
}) | ||
..body = jsonEncode({ | ||
"model": "gpt-4o", | ||
"name": "Composites AI", | ||
'description': | ||
"You are an expert in composite materials and structures. Please answer questions related to composites simulation, design and manufacturing." | ||
}); | ||
|
||
// 2. Send the request | ||
final http.StreamedResponse streamedResponse = await client.send(request); | ||
final String responseBody = await streamedResponse.stream.bytesToString(); | ||
|
||
// 3. Handle success or throw an error | ||
if (streamedResponse.statusCode == 200 || | ||
streamedResponse.statusCode == 201) { | ||
final Map<String, dynamic> jsonResponse = jsonDecode(responseBody); | ||
return Assistant.fromJson(jsonResponse); | ||
} else { | ||
// Provide as much detail as possible for debugging | ||
throw HttpException( | ||
'Failed to create assistant. ' | ||
'Status: ${streamedResponse.statusCode}, ' | ||
'Response: $responseBody', | ||
uri: request.url, | ||
); | ||
} | ||
} | ||
|
||
@override | ||
String getCompositeAssistantId() { | ||
return "asst_pxUDI3A9Q8afCqT9cqgUkWQP"; | ||
} | ||
|
||
@override | ||
Future<Thread> createThread() async { | ||
final request = | ||
http.Request('POST', Uri.parse(ApiConstants.threadsEndpoint)) | ||
..headers.addAll({ | ||
'Content-Type': 'application/json', | ||
'Authorization': 'Bearer ${ApiConstants.apiKey}', | ||
'OpenAI-Beta': 'assistants=v2', | ||
}); | ||
|
||
// 2. Send the request | ||
final http.StreamedResponse streamedResponse = await client.send(request); | ||
final String responseBody = await streamedResponse.stream.bytesToString(); | ||
|
||
// 3. Handle success or throw an error | ||
if (streamedResponse.statusCode == 200 || | ||
streamedResponse.statusCode == 201) { | ||
final Map<String, dynamic> jsonResponse = jsonDecode(responseBody); | ||
return Thread.fromJson(jsonResponse); | ||
} else { | ||
// Provide as much detail as possible for debugging | ||
throw HttpException( | ||
'Failed to create a thread. ' | ||
'Status: ${streamedResponse.statusCode}, ' | ||
'Response: $responseBody', | ||
uri: request.url, | ||
); | ||
} | ||
} | ||
} |
50 changes: 50 additions & 0 deletions
50
packages/data/lib/repositories/messages_repository_impl.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import 'dart:convert'; | ||
import 'dart:io'; | ||
|
||
import 'package:domain/entities/assistant_message.dart'; | ||
import 'package:domain/entities/message.dart'; | ||
import 'package:domain/entities/thread.dart'; | ||
import 'package:domain/repositories_abstract/messages_repository.dart'; | ||
import 'package:http/http.dart' as http; | ||
|
||
import '../utils/api_constants.dart'; | ||
|
||
class MessagesRepositoryImp implements MessagesRepository { | ||
final http.Client client; | ||
|
||
MessagesRepositoryImp({required this.client}); | ||
|
||
@override | ||
Future<AssistantMessage> createMessage(Thread thread, Message message) async { | ||
final request = http.Request('POST', | ||
Uri.parse(ApiConstants.threadsEndpoint + "/${thread.id}/messages")) | ||
..headers.addAll({ | ||
'Content-Type': 'application/json', | ||
'Authorization': 'Bearer ${ApiConstants.apiKey}', | ||
'OpenAI-Beta': 'assistants=v2', | ||
}) | ||
..body = jsonEncode({ | ||
"role": "user", | ||
"content": message.content, | ||
}); | ||
|
||
// 2. Send the request | ||
final http.StreamedResponse streamedResponse = await client.send(request); | ||
final String responseBody = await streamedResponse.stream.bytesToString(); | ||
|
||
// 3. Handle success or throw an error | ||
if (streamedResponse.statusCode == 200 || | ||
streamedResponse.statusCode == 201) { | ||
final Map<String, dynamic> jsonResponse = jsonDecode(responseBody); | ||
return AssistantMessage.fromJson(jsonResponse); | ||
} else { | ||
// Provide as much detail as possible for debugging | ||
throw HttpException( | ||
'Failed to create a message. ' | ||
'Status: ${streamedResponse.statusCode}, ' | ||
'Response: $responseBody', | ||
uri: request.url, | ||
); | ||
} | ||
} | ||
} |
45 changes: 45 additions & 0 deletions
45
packages/data/lib/repositories/threads_repository_impl.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import 'dart:convert'; | ||
import 'dart:io'; | ||
|
||
import 'package:domain/entities/thread.dart'; | ||
import 'package:domain/repositories_abstract/threads_repository.dart'; | ||
import 'package:http/http.dart' as http; | ||
|
||
import '../utils/api_constants.dart'; | ||
|
||
class ThreadsRepositoryImp implements ThreadsRepository { | ||
final http.Client client; | ||
|
||
ThreadsRepositoryImp( | ||
{required this.client}); | ||
|
||
@override | ||
Future<Thread> createThread() async { | ||
final request = | ||
http.Request('POST', Uri.parse(ApiConstants.threadsEndpoint)) | ||
..headers.addAll({ | ||
'Content-Type': 'application/json', | ||
'Authorization': 'Bearer ${ApiConstants.apiKey}', | ||
'OpenAI-Beta': 'assistants=v2', | ||
}); | ||
|
||
// 2. Send the request | ||
final http.StreamedResponse streamedResponse = await client.send(request); | ||
final String responseBody = await streamedResponse.stream.bytesToString(); | ||
|
||
// 3. Handle success or throw an error | ||
if (streamedResponse.statusCode == 200 || | ||
streamedResponse.statusCode == 201) { | ||
final Map<String, dynamic> jsonResponse = jsonDecode(responseBody); | ||
return Thread.fromJson(jsonResponse); | ||
} else { | ||
// Provide as much detail as possible for debugging | ||
throw HttpException( | ||
'Failed to create a thread. ' | ||
'Status: ${streamedResponse.statusCode}, ' | ||
'Response: $responseBody', | ||
uri: request.url, | ||
); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
class Assistant { | ||
final String id; | ||
final String object; | ||
final int createdAt; | ||
final String name; | ||
final String description; | ||
final String model; | ||
final dynamic instructions; | ||
final List<dynamic> tools; | ||
final double topP; | ||
final double temperature; | ||
final Map<String, dynamic> toolResources; | ||
final Map<String, dynamic> metadata; | ||
final String responseFormat; | ||
|
||
Assistant({ | ||
required this.id, | ||
required this.object, | ||
required this.createdAt, | ||
required this.name, | ||
required this.description, | ||
required this.model, | ||
required this.instructions, | ||
required this.tools, | ||
required this.topP, | ||
required this.temperature, | ||
required this.toolResources, | ||
required this.metadata, | ||
required this.responseFormat, | ||
}); | ||
|
||
/// Parses an [Assistant] from a JSON object | ||
factory Assistant.fromJson(Map<String, dynamic> json) { | ||
return Assistant( | ||
id: json['id'] as String, | ||
object: json['object'] as String, | ||
createdAt: json['created_at'] as int, | ||
name: json['name'] as String, | ||
description: json['description'] as String, | ||
model: json['model'] as String, | ||
instructions: json['instructions'], // can be null | ||
tools: (json['tools'] ?? []) as List<dynamic>, | ||
topP: (json['top_p'] ?? 1.0).toDouble(), | ||
temperature: (json['temperature'] ?? 1.0).toDouble(), | ||
toolResources: (json['tool_resources'] ?? {}) as Map<String, dynamic>, | ||
metadata: (json['metadata'] ?? {}) as Map<String, dynamic>, | ||
responseFormat: json['response_format'] as String? ?? 'auto', | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
class AssistantMessage { | ||
final String id; | ||
final String object; | ||
final int createdAt; | ||
final String? assistantId; | ||
final String threadId; | ||
final String? runId; | ||
final String role; | ||
final List<Content> content; | ||
final List<dynamic> attachments; | ||
final Map<String, dynamic> metadata; | ||
|
||
AssistantMessage({ | ||
required this.id, | ||
required this.object, | ||
required this.createdAt, | ||
this.assistantId, | ||
required this.threadId, | ||
this.runId, | ||
required this.role, | ||
required this.content, | ||
required this.attachments, | ||
required this.metadata, | ||
}); | ||
|
||
factory AssistantMessage.fromJson(Map<String, dynamic> json) { | ||
var contentList = <Content>[]; | ||
if (json['content'] != null) { | ||
contentList = (json['content'] as List) | ||
.map((i) => Content.fromJson(i)) | ||
.toList(); | ||
} | ||
|
||
return AssistantMessage( | ||
id: json['id'], | ||
object: json['object'], | ||
createdAt: json['created_at'], | ||
assistantId: json['assistant_id'], | ||
threadId: json['thread_id'], | ||
runId: json['run_id'], | ||
role: json['role'], | ||
content: contentList, | ||
attachments: json['attachments'] ?? [], | ||
metadata: json['metadata'] ?? {}, | ||
); | ||
} | ||
|
||
Map<String, dynamic> toJson() => { | ||
'id': id, | ||
'object': object, | ||
'created_at': createdAt, | ||
'assistant_id': assistantId, | ||
'thread_id': threadId, | ||
'run_id': runId, | ||
'role': role, | ||
'content': content.map((e) => e.toJson()).toList(), | ||
'attachments': attachments, | ||
'metadata': metadata, | ||
}; | ||
} | ||
|
||
class Content { | ||
final String type; | ||
final TextContent text; | ||
|
||
Content({required this.type, required this.text}); | ||
|
||
factory Content.fromJson(Map<String, dynamic> json) { | ||
return Content( | ||
type: json['type'], | ||
text: TextContent.fromJson(json['text']), | ||
); | ||
} | ||
|
||
Map<String, dynamic> toJson() => { | ||
'type': type, | ||
'text': text.toJson(), | ||
}; | ||
} | ||
|
||
class TextContent { | ||
final String value; | ||
final List<dynamic> annotations; | ||
|
||
TextContent({required this.value, required this.annotations}); | ||
|
||
factory TextContent.fromJson(Map<String, dynamic> json) { | ||
return TextContent( | ||
value: json['value'], | ||
annotations: json['annotations'] ?? [], | ||
); | ||
} | ||
|
||
Map<String, dynamic> toJson() => { | ||
'value': value, | ||
'annotations': annotations, | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
class Thread { | ||
final String id; | ||
final String object; | ||
final int createdAt; | ||
final Map<String, dynamic> metadata; | ||
final Map<String, dynamic> toolResources; | ||
|
||
Thread({ | ||
required this.id, | ||
required this.object, | ||
required this.createdAt, | ||
required this.metadata, | ||
required this.toolResources, | ||
}); | ||
|
||
factory Thread.fromJson(Map<String, dynamic> json) { | ||
return Thread( | ||
id: json['id'], | ||
object: json['object'], | ||
createdAt: json['created_at'], | ||
metadata: json['metadata'] ?? {}, | ||
toolResources: json['tool_resources'] ?? {}, | ||
); | ||
} | ||
|
||
Map<String, dynamic> toJson() => { | ||
'id': id, | ||
'object': object, | ||
'created_at': createdAt, | ||
'metadata': metadata, | ||
'tool_resources': toolResources, | ||
}; | ||
} |
Oops, something went wrong.