Skip to content
Open
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
4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
[workspace]
members = [
"crates/neatcoder",
"crates/parser"
"crates/parser",
"crates/oai",
"crates/wasmer"
]
exclude = [
"examples/projects/*/jobs/codebase",
Expand Down
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,13 @@ Install VS extension:
<https://marketplace.visualstudio.com/items?itemName=amodio.tsl-problem-matcher>

Copy `tasks.json` and `launch.json` from vscode to .vscode folder



## To compile oai crate

As default native:
`cargo build`

As a Wasm Lib:
`cargo build --target wasm32-unknown-unknown --features wasm --no-default-features`
2 changes: 1 addition & 1 deletion bin/create_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def process_file(input_filename, output_filename):
# Check for methods by looking for lines with parentheses and ignore them
if "(" in stripped_line or ")" in stripped_line:
continue
elif stripped_line.endswith(";"):
elif stripped_line.endswith(";"): ## Can either be a method or readonly field
# If it's a readonly field, remove the readonly keyword
# Ensure indentation when adding to output
output_lines.append(" " + stripped_line.replace("readonly ", ""))
Expand Down
2 changes: 2 additions & 0 deletions crates/neatcoder/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ crate-type = ["cdylib"]

[dependencies]
parser = { path = "../parser" }
oai = { path = "../oai", default-features = false, features = ["wasm"] }
wasmer = { path = "../wasmer" }

anyhow = "1.0"
bytes = "1.4.0"
Expand Down
33 changes: 14 additions & 19 deletions crates/neatcoder/src/endpoints/get_chat_title.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
use anyhow::{anyhow, Result};
use js_sys::Function;

use crate::openai::{
msg::{GptRole, OpenAIMsg},
params::{OpenAIModels, OpenAIParams},
request::chat_raw,
use oai::models::{
chat::{
params::wasm::ChatParamsWasm as ChatParams, request::wasm::chat_raw,
},
message::wasm::GptMessageWasm as GptMessage,
model::GptModel,
role::Role as GptRole,
};

pub async fn get_chat_title(
Expand All @@ -13,16 +15,13 @@ pub async fn get_chat_title(
) -> Result<String> {
let mut prompts = Vec::new();

prompts.push(OpenAIMsg {
role: GptRole::System,
content: String::from(
"
prompts.push(GptMessage::new(GptRole::System, String::from(
"
- Context: Briefly describe the key topics or themes of the chat.
- Title Specifications: The title should be concise, and not exceed 6 words. It should reflect the tone of the chat (e.g., professional, casual, informative, provocative, etc.).
- Output: Provide a title that encapsulates the main focus of the chat.
",
),
});
",
)));

let main_prompt = format!(
"
Expand All @@ -33,15 +32,11 @@ The title of the prompt is:",
msg
);

prompts.push(OpenAIMsg {
role: GptRole::User,
content: main_prompt,
});
prompts.push(GptMessage::new(GptRole::User, main_prompt));

let prompts = prompts.iter().map(|x| x).collect::<Vec<&OpenAIMsg>>();
let prompts = prompts.iter().map(|x| x).collect::<Vec<&GptMessage>>();

let ai_params =
OpenAIParams::empty(OpenAIModels::Gpt35Turbo).max_tokens(15);
let ai_params = ChatParams::empty(GptModel::Gpt35Turbo).max_tokens(15);

let chat =
chat_raw(request_callback, &ai_params, &prompts, &[], &[]).await?;
Expand Down
23 changes: 9 additions & 14 deletions crates/neatcoder/src/endpoints/scaffold_project.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
use anyhow::{anyhow, Result};
use js_sys::{Function, JsString};
use oai::models::{
chat::params::wasm::ChatParamsWasm as ChatParams,
message::wasm::GptMessageWasm as GptMessage, role::Role as GptRole,
};
use serde::{Deserialize, Serialize};
use serde_json::{Map, Value};
use std::{
Expand All @@ -12,10 +16,6 @@ use wasm_bindgen::prelude::wasm_bindgen;
use crate::{
consts::{CONFIG_EXTENSIONS, CONFIG_FILES},
models::app_data::language::Language,
openai::{
msg::{GptRole, OpenAIMsg},
params::OpenAIParams,
},
utils::write_json,
};

Expand All @@ -41,18 +41,16 @@ impl ScaffoldParams {

pub async fn scaffold_project(
language: &Language,
ai_params: &OpenAIParams,
ai_params: &ChatParams,
client_params: &ScaffoldParams,
request_callback: &Function,
) -> Result<(Value, Files)> {
let mut prompts = Vec::new();

prompts.push(OpenAIMsg {
role: GptRole::System,
content: format!(
prompts.push(GptMessage::new(GptRole::System,format!(
"You are a software engineer who is specialised in building software in {}.", language.name()
),
});
));

// TODO: We should add the Database and API interfaces in previous messages, and add the name of the files here in order to index them
let main_prompt = format!("
Expand All @@ -63,12 +61,9 @@ Based on the information provided write the project's folder structure, starting

Answer in JSON format (Do not forget to start with ```json). For each file provide a brief description included in the json", language.name(), client_params.specs);

prompts.push(OpenAIMsg {
role: GptRole::User,
content: main_prompt,
});
prompts.push(GptMessage::new(GptRole::User, main_prompt));

let prompts = prompts.iter().map(|x| x).collect::<Vec<&OpenAIMsg>>();
let prompts = prompts.iter().map(|x| x).collect::<Vec<&GptMessage>>();

let (_, mut scaffold_json) =
write_json(&ai_params, &prompts, request_callback).await?;
Expand Down
65 changes: 31 additions & 34 deletions crates/neatcoder/src/endpoints/stream_code.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
use anyhow::{anyhow, Result};
use js_sys::JsString;
use oai::models::{
chat::{
params::wasm::ChatParamsWasm as ChatParams, request::request_stream,
},
message::{
wasm::GptMessageWasm as GptMessage, GptMessage as GptMessageInner,
},
role::Role as GptRole,
};
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
use std::{collections::BTreeMap, ops::Deref};
use wasm_bindgen::prelude::wasm_bindgen;
use wasmer::log;

use crate::{
models::app_data::{interfaces::AsContext, AppData},
openai::{
msg::{GptRole, OpenAIMsg},
params::OpenAIParams,
request::request_stream,
},
utils::log,
};
use crate::models::app_data::{interfaces::AsContext, AppData};

#[wasm_bindgen]
#[derive(Debug, Deserialize, Serialize, Clone)]
Expand Down Expand Up @@ -40,7 +42,7 @@ impl CodeGenParams {

pub fn stream_code(
app_state: &AppData,
ai_params: &OpenAIParams,
ai_params: &ChatParams,
task_params: &CodeGenParams,
codebase: BTreeMap<String, String>,
) -> Result<String> {
Expand Down Expand Up @@ -72,35 +74,28 @@ pub fn stream_code(
anyhow!("It seems that the the field `specs` is missing..")
})?;

prompts.push(OpenAIMsg {
role: GptRole::System,
content: format!(
prompts.push(GptMessage::new(
GptRole::System,
format!(
"You are a software engineer who is specialised in {}.",
language.name()
),
});
));

prompts.push(OpenAIMsg {
role: GptRole::User,
content: String::from(project_description),
});
prompts.push(GptMessage::new(
GptRole::User,
String::from(project_description),
));

for file in codebase.keys() {
let code = codebase
.get(file)
.ok_or_else(|| anyhow!("Unable to find fild {:?}", file))?;

prompts.push(OpenAIMsg {
role: GptRole::User,
content: code.clone(),
});
prompts.push(GptMessage::new(GptRole::User, code.clone()));
}

prompts.push(OpenAIMsg {
role: GptRole::User,
// Needs to be optimized
content: project_scaffold.to_string(),
});
prompts.push(GptMessage::new(GptRole::User, project_scaffold.to_string()));

let mut main_prompt = format!(
"
Expand Down Expand Up @@ -132,14 +127,16 @@ pub fn stream_code(
));
}

prompts.push(OpenAIMsg {
role: GptRole::User,
content: main_prompt,
});
prompts.push(GptMessage::new(GptRole::User, main_prompt));

// Assuming prompts is a Vec<&GptMessageWasm>
let msgs: Vec<&GptMessageInner> =
prompts.iter().map(|m_wasm| (*m_wasm).deref()).collect();

let prompts = prompts.iter().map(|x| x).collect::<Vec<&OpenAIMsg>>();
let prompts_slice: &[&GptMessageInner] = &msgs;

let request_body = request_stream(ai_params, &prompts, &[], &[])?;
let request_body =
request_stream(ai_params.deref(), &prompts_slice, &[], &[])?;

Ok(request_body)
}
Loading