Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: profile #70

Merged
merged 8 commits into from
Oct 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ chrono = "0.4.38"
async-stream = "0.3.5"
anyhow = "1.0.89"
itertools = "0.13.0"
sysinfo = "0.31.4"

[dev-dependencies]
claim = "0.5.0"
Expand Down
52 changes: 52 additions & 0 deletions core/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# AI Likes Human Core

## Domains

### Assistant

Everything related to Assistant and it's storage.
Thread, Message, Run, Etc..

Very closed to OpenAI Assistant API.

### Chat Completion

Everything related to LLM calling in the OpenAI Chat Completion API format.

### Configuration

App configuration. Mainly storage of various configurations.
For example:

- Api Keys
- Selected LLM
- LLM Parameters

### Entities

Database entities generated by `sea-orm` migration system.

### infrastructure

Infrastructure code used by every other domains.

### llm

LLM Inference. Implementation of every used LLM in this app.
For example:

- OpenAI
- Anthropic Claude
- LLamaCPP
- Etc...

Also implement agent creation. Creation of a custom agent based on existing LLM (using langgraph rust).
Can add, tool, chain of tought, etc..

### profile

User profiles. For example system prompt for a `Software Engineer`

### utils

Utilities functions used in every other domains
6 changes: 6 additions & 0 deletions core/migration/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ mod m20220101_000002_create_thread_table;
mod m20220101_000003_create_run_table;
mod m20220101_000004_create_message_table;
mod m20220101_000005_seed_default_llm_configuration;
mod m20220101_000006_create_profile_table;
mod m20220101_000007_seed_profile_software_engineer;

pub use m20220101_000007_seed_profile_software_engineer::SOFTWARE_ENGINEER_PROFILE_NAME;

pub struct Migrator;

Expand All @@ -18,6 +22,8 @@ impl MigratorTrait for Migrator {
Box::new(m20220101_000003_create_run_table::Migration),
Box::new(m20220101_000004_create_message_table::Migration),
Box::new(m20220101_000005_seed_default_llm_configuration::Migration),
Box::new(m20220101_000006_create_profile_table::Migration),
Box::new(m20220101_000007_seed_profile_software_engineer::Migration),
]
}
}
Expand Down
46 changes: 46 additions & 0 deletions core/migration/src/m20220101_000006_create_profile_table.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
use sea_orm_migration::prelude::*;

#[derive(DeriveMigrationName)]
pub struct Migration;

#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.create_table(
Table::create()
.table(Profile::Table)
.if_not_exists()
.col(
ColumnDef::new(Profile::Id)
.integer()
.not_null()
.auto_increment()
.primary_key(),
)
.col(
ColumnDef::new(Profile::Name)
.string()
.unique_key()
.not_null(),
)
.col(ColumnDef::new(Profile::Prompt).string().not_null())
.to_owned(),
)
.await
}

async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.drop_table(Table::drop().table(Profile::Table).to_owned())
.await
}
}

#[derive(DeriveIden)]
pub enum Profile {
Table,
Id,
Name,
Prompt,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
use sea_orm_migration::prelude::*;

use crate::m20220101_000006_create_profile_table::Profile;

#[derive(DeriveMigrationName)]
pub struct Migration;

pub static SOFTWARE_ENGINEER_PROFILE_NAME: &str = "Senior Software Engineer";
static SOFTWARE_ENGINEER_PROFILE_PROMPT: &str = r#"
# audience
A senior software developer.

# style
Be straight forward and concise. Only give explanation if asked.

## References
When the answer contains an external project, dependency, command line tools, application or executable, a library or any external references: ALWAYS provide sources and give an URL to the reference. Prefer sources of how to use and install.

## Code Format
When asked about code questions, give code example.
Provide library answer only if the question is explicitly about code and a language is specified.
If an existing library (or many libraries) already exist for the question, provide it.
"#;

#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
let insert: InsertStatement = Query::insert()
.into_table(Profile::Table)
.columns([Profile::Name, Profile::Prompt])
.values_panic([
SOFTWARE_ENGINEER_PROFILE_NAME.into(),
SOFTWARE_ENGINEER_PROFILE_PROMPT.into(),
])
.to_owned();

manager.exec_stmt(insert).await
}

async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
let delete = Query::delete()
.from_table(Profile::Table)
.and_where(Expr::col(Profile::Name).eq(SOFTWARE_ENGINEER_PROFILE_NAME))
.to_owned();

manager.exec_stmt(delete).await
}
}
44 changes: 32 additions & 12 deletions core/src/api_facade.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
use std::sync::Arc;

use crate::{
chat_completion::{ChatCompletionMessageDto, ChatCompletionResult, ChatCompletionStream},
chat_completion::{
inference::InferenceArgs, ChatCompletionMessageDto, ChatCompletionResult,
ChatCompletionStream,
},
configuration::ConfigurationDto,
profile::domain::dto::ProfileDto,
AppContainer,
};

Expand All @@ -20,25 +24,31 @@ impl ApiFacade {
model: &str,
messages: &Vec<ChatCompletionMessageDto>,
) -> ChatCompletionResult {
let factory = self
.container
.chat_completion_module
.get_inference_factory();
let inference = self.container.chat_completion_module.get_inference();

factory.invoke(model, messages).await
inference
.invoke(InferenceArgs {
model: model.to_string(),
messages: messages.clone(),
..Default::default()
})
.await
}

pub fn chat_completion_stream(
pub async fn chat_completion_stream(
&self,
model: &str,
messages: &Vec<ChatCompletionMessageDto>,
) -> ChatCompletionStream {
let factory = self
.container
.chat_completion_module
.get_inference_factory();
let inference = self.container.chat_completion_module.get_inference();

factory.stream(model, messages)
inference
.stream(InferenceArgs {
model: model.to_string(),
messages: messages.clone(),
..Default::default()
})
.await
}

pub async fn find_configuration(
Expand All @@ -64,4 +74,14 @@ impl ApiFacade {

configuration_service.upsert(key, value).await
}

pub async fn get_selected_profiles(
&self,
) -> Result<Vec<ProfileDto>, Box<dyn std::error::Error + Send>> {
self.container
.profile_module
.get_selected_profiles_service()
.find_selected_profiles()
.await
}
}
15 changes: 12 additions & 3 deletions core/src/app_container.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::{error::Error, sync::Arc};
use crate::{
app_configuration::CoreConfiguration, assistant::AgentDIModule,
chat_completion::ChatCompletionDIModule, configuration::ConfigurationDIModule,
infrastructure::sea_orm::ConnectionFactory, llm::LLMDIModule,
infrastructure::sea_orm::ConnectionFactory, llm::LLMDIModule, profile::ProfileDIModule,
};

pub struct AppContainer {
Expand All @@ -12,6 +12,7 @@ pub struct AppContainer {
pub configuration_module: Arc<ConfigurationDIModule>,
pub llm_module: Arc<LLMDIModule>,
pub chat_completion_module: Arc<ChatCompletionDIModule>,
pub profile_module: Arc<ProfileDIModule>,
pub agent_module: AgentDIModule,
}

Expand All @@ -21,8 +22,15 @@ impl AppContainer {
let connection: Arc<::sea_orm::DatabaseConnection> = connection_factory.create().await?;

let configuration_module = Arc::new(ConfigurationDIModule::new(Arc::clone(&connection)));
let llm_module = Arc::new(LLMDIModule::new(configuration_module.clone()));
let chat_completion_module = Arc::new(ChatCompletionDIModule::new(Arc::clone(&llm_module)));
let profile_module = Arc::new(ProfileDIModule::new(Arc::clone(&connection)));
let llm_module = Arc::new(LLMDIModule::new(
configuration_module.clone(),
profile_module.clone(),
));
let chat_completion_module = Arc::new(ChatCompletionDIModule::new(
Arc::clone(&llm_module),
Arc::clone(&profile_module),
));
let agent_module: AgentDIModule =
AgentDIModule::new(Arc::clone(&connection), Arc::clone(&chat_completion_module));

Expand All @@ -32,6 +40,7 @@ impl AppContainer {
configuration_module,
llm_module,
chat_completion_module,
profile_module,
agent_module,
})
}
Expand Down
2 changes: 1 addition & 1 deletion core/src/assistant/domain/stream_thread_run_service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ impl StreamThreadRunService {
yield ThreadEventDto::thread_message_created(&response_message);
yield ThreadEventDto::thread_message_in_progress(&response_message);

let mut stream = inference_service.stream(&run.model, &messages);
let mut stream = inference_service.stream(&run.model, &messages).await;
while let Some(chunk) = stream.next().await {
let chunk = match chunk {
Ok(chunk) => chunk,
Expand Down
24 changes: 18 additions & 6 deletions core/src/assistant/domain/thread_chat_completions_inference.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,34 @@
use std::sync::Arc;

use crate::chat_completion::{self, ChatCompletionMessageDto, ChatCompletionStream};
use crate::chat_completion::{
self, inference::InferenceArgs, ChatCompletionMessageDto, ChatCompletionStream,
};

use super::dto::ThreadMessageDto;

pub struct ThreadChatCompletionInference {
inference_service: Arc<chat_completion::InferenceService>,
inference: Arc<dyn chat_completion::inference::Inference>,
}

impl ThreadChatCompletionInference {
pub fn new(inference_service: Arc<chat_completion::InferenceService>) -> Self {
Self { inference_service }
pub fn new(inference: Arc<dyn chat_completion::inference::Inference>) -> Self {
Self { inference }
}

pub fn stream(&self, model: &str, messages: &Vec<ThreadMessageDto>) -> ChatCompletionStream {
pub async fn stream(
&self,
model: &str,
messages: &Vec<ThreadMessageDto>,
) -> ChatCompletionStream {
let messages: Vec<ChatCompletionMessageDto> =
messages.iter().map(|m| m.clone().into()).collect();

self.inference_service.stream(model, &messages)
self.inference
.stream(InferenceArgs {
model: model.to_string(),
messages: messages,
..Default::default()
})
.await
}
}
6 changes: 2 additions & 4 deletions core/src/assistant/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,9 @@ impl AgentDIModule {
}

pub fn get_thread_inference_service(&self) -> Arc<ThreadChatCompletionInference> {
let chat_completion_inference_service = self.chat_completion_module.get_inference_factory();
let inference = self.chat_completion_module.get_inference();

Arc::new(ThreadChatCompletionInference::new(
chat_completion_inference_service,
))
Arc::new(ThreadChatCompletionInference::new(inference))
}

pub fn get_run_status_mutator(&self) -> Arc<RunStatusMutator> {
Expand Down
7 changes: 7 additions & 0 deletions core/src/chat_completion/domain/dto/completion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@ impl ChatCompletionMessageDto {
}
}

pub fn system(content: &str) -> Self {
ChatCompletionMessageDto {
role: "system".to_string(),
content: vec![ApiMessageContent::text(content)],
}
}

pub fn to_string_content(&self) -> String {
self.content
.iter()
Expand Down
Loading