Skip to content

Commit

Permalink
prepare for multiple provider
Browse files Browse the repository at this point in the history
  • Loading branch information
aeltorio committed Oct 3, 2024
1 parent 297b7b0 commit d7ecfa2
Show file tree
Hide file tree
Showing 8 changed files with 296 additions and 228 deletions.
366 changes: 183 additions & 183 deletions package-lock.json

Large diffs are not rendered by default.

12 changes: 6 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "sctg-ai-pane",
"version": "0.0.2",
"version": "0.0.3",
"repository": {
"type": "git",
"url": "https://github.com/OfficeDev/Office-Addin-TaskPane-React.git"
Expand All @@ -27,20 +27,20 @@
},
"dependencies": {
"@fluentui/react-components": "^9.54.17",
"@fluentui/react-icons": "^2.0.259",
"@fluentui/react-icons": "^2.0.260",
"core-js": "^3.38.1",
"es6-promise": "^4.2.8",
"@sctg/ai-sdk": "^0.7.0",
"@sctg/ai-sdk": "^0.7.1",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"regenerator-runtime": "^0.14.1"
},
"devDependencies": {
"@babel/core": "^7.25.2",
"@babel/preset-typescript": "^7.24.7",
"@babel/core": "^7.25.7",
"@babel/preset-typescript": "^7.25.7",
"@types/office-js": "^1.0.433",
"@types/office-runtime": "^1.0.35",
"@types/react": "^18.3.10",
"@types/react": "^18.3.11",
"@types/react-dom": "^18.3.0",
"@types/webpack": "^5.28.5",
"acorn": "^8.12.1",
Expand Down
18 changes: 18 additions & 0 deletions src/aipane/AIPrompt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
=========================================================
*/

import config from "../config.json";
export interface AIPrompt {
id: string;
system: string;
Expand All @@ -16,3 +17,20 @@ export interface AIModel {
name: string;
default: boolean;
}

export interface AIProvider {
default: boolean;
name: string;
baseUrl: string;
basePath: string;
apiKey: string;
models: AIModel[];
}

export function getDefaultProvider(): AIProvider {
return config.providers.filter((provider: AIProvider) => provider.default)[0];
}

export function getProvider(providerName: string): AIProvider {
return config.providers.filter((provider: AIProvider) => provider.name === providerName)[0];
}
25 changes: 19 additions & 6 deletions src/aipane/aipane.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,27 @@

import { Groq } from "@sctg/ai-sdk";
import config from "../config.json";
import type { AIPrompt } from "./AIPrompt";
import type { AIPrompt, AIProvider } from "./AIPrompt";

async function groqRequest(model: string, apiKey: string, systemText: string, usertext: string): Promise<string> {
async function groqRequest(
provider: AIProvider,
model: string,
apiKey: string,
systemText: string,
usertext: string
): Promise<string> {
const groq = new Groq({
baseURL: "https://api.groq.com",
basePath: "/openai/v1",
baseURL: provider.baseUrl,
basePath: provider.basePath,
disableCorsCheck: false,
apiKey,
dangerouslyAllowBrowser: true,
// fetch: async (url: any, init?: any): Promise<any> => {
// console.log("About to make a request", url, init);
// const response = await fetch(url, { mode: "no-cors", ...init });
// console.log("Got response", response);
// return response;
// },
});
const chatCompletion = await groq.chat.completions.create({
messages: [
Expand Down Expand Up @@ -41,14 +54,14 @@ function getPrompt(id: string): AIPrompt {
return prompts.find((prompt) => prompt.id === id) || prompts[0];
}

export async function insertText(model: string, apiKey: string, id: string, userText: string) {
export async function insertText(provider: AIProvider, model: string, apiKey: string, id: string, userText: string) {
const { system, user } = getPrompt(id);
try {
console.log(`Prompt: ${id}`);
console.log(`System text: \n${system}`);
console.log(`User: ${user}`);
console.log(`User text: \n${userText}`);
let aiText = await groqRequest(model, apiKey, system, `${user}\n${userText}`);
let aiText = await groqRequest(provider, model, apiKey, system, `${user}\n${userText}`);
console.log(`AI response (${model}): \n${aiText}`);
aiText = aiText.replace(/\n/g, "<br>");
Office.context.mailbox.item?.body.setSelectedDataAsync(
Expand Down
19 changes: 13 additions & 6 deletions src/aipane/components/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { insertText } from "../aipane";
import HeroApiKey from "./HeroApiKey";
import HeroComboPrompts from "./HeroComboPrompts";
import HeroModels from "./HeroModels";
import { getDefaultProvider } from "../AIPrompt";

interface AppProps {
title: string;
Expand All @@ -26,6 +27,7 @@ const useStyles = makeStyles({
});

const App: React.FC<AppProps> = (props: AppProps) => {
const provider = getDefaultProvider();
const styles = useStyles();
const [apiKey, setApiKey] = useState<string | null>(null);
const [prompt, setPrompt] = useState<string | null>(null);
Expand All @@ -42,7 +44,7 @@ const App: React.FC<AppProps> = (props: AppProps) => {
];

useEffect(() => {
const storedApiKey = localStorage.getItem("apiKey");
const storedApiKey = localStorage.getItem(provider.apiKey);
if (!storedApiKey) {
setShowApiKeyInput(true);
} else {
Expand All @@ -60,7 +62,7 @@ const App: React.FC<AppProps> = (props: AppProps) => {

const handleApiKeySubmit = () => {
if (apiKey) {
localStorage.setItem("apiKey", apiKey);
localStorage.setItem(provider.apiKey, apiKey);
setShowApiKeyInput(false);
}
};
Expand All @@ -70,19 +72,24 @@ const App: React.FC<AppProps> = (props: AppProps) => {
};

const handlePromptSubmit = (userText: string) => {
const apiKey = localStorage.getItem("apiKey");
insertText(model, apiKey, prompt, `${userText}`);
const apiKey = localStorage.getItem(provider.apiKey);
insertText(provider, model, apiKey, prompt, `${userText}`);
};

return (
<div className={styles.root}>
<Header logo="assets/logo-filled.png" title={props.title} message="AI emailer" />
{showApiKeyInput ? (
<HeroApiKey apiKey={apiKey} onApiKeyChange={handleApiKeyChange} onApiKeySubmit={handleApiKeySubmit} />
<HeroApiKey
apiKey={apiKey}
onApiKeyChange={handleApiKeyChange}
onApiKeySubmit={handleApiKeySubmit}
provider={provider}
/>
) : (
<>
<HeroList message="Ask Llama" items={listItems} />
<HeroModels onChange={handleModelChange} />
<HeroModels onChange={handleModelChange} provider={provider} />
<HeroComboPrompts onChange={handlePromptChange} />
<TextInsertion insertText={handlePromptSubmit} basePrompt={""} />
</>
Expand Down
6 changes: 4 additions & 2 deletions src/aipane/components/HeroApiKey.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
*/
import * as React from "react";
import { makeStyles, useId, Button, Input, Label } from "@fluentui/react-components";
import { AIProvider } from "../AIPrompt";

interface HeroApiKeyProps {
provider: AIProvider;
apiKey: string | null;
onApiKeyChange: (event: React.ChangeEvent<HTMLInputElement>) => void;
onApiKeySubmit: () => void;
Expand All @@ -27,13 +29,13 @@ const useStyles = makeStyles({
},
});

const HeroApiKey: React.FC<HeroApiKeyProps> = ({ apiKey, onApiKeyChange, onApiKeySubmit }) => {
const HeroApiKey: React.FC<HeroApiKeyProps> = ({ apiKey, onApiKeyChange, onApiKeySubmit, provider }) => {
const styles = useStyles();
const inputId = useId("input");
return (
<div className={styles.root}>
<Label htmlFor={inputId} size="large">
Grok API Key
{provider.name} API Key
</Label>
<Input
className={styles.input}
Expand Down
20 changes: 10 additions & 10 deletions src/aipane/components/HeroModels.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@
import * as React from "react";
import { Dropdown, Label, makeStyles, Option, useId } from "@fluentui/react-components";
import { useState, useEffect } from "react";
import config from "../../config.json"; // Assurez-vous que le chemin est correct
import type { AIModel } from "../AIPrompt";
import { type AIModel, type AIProvider } from "../AIPrompt";

interface HeroModelsProps {
onChange: (selectedValue: string) => void;
provider: AIProvider;
//readValue: () => string;
}

function getDefaultModel(): AIModel {
return config.models.filter((model: AIModel) => model.default)[0];
function getDefaultModel(provider: AIProvider): AIModel {
return provider.models.filter((model: AIModel) => model.default)[0];
}
const useStyles = makeStyles({
root: {
Expand All @@ -32,14 +32,14 @@ const useStyles = makeStyles({
},
});

const HeroModels: React.FC<HeroModelsProps> = ({ onChange }) => {
const HeroModels: React.FC<HeroModelsProps> = ({ onChange, provider }) => {
const styles = useStyles();
const selectId = useId("select");
const [selectedValue, setSelectedValue] = useState<string>(getDefaultModel().id);
const [selectedValue, setSelectedValue] = useState<string>(getDefaultModel(provider).id);

const handleChange = (event: React.FormEvent<HTMLButtonElement>, option?: any) => {
event.preventDefault();
const newValue = option.nextOption?.value || getDefaultModel().id;
const newValue = option.nextOption?.value || getDefaultModel(provider).id;
setSelectedValue(newValue);
onChange(newValue);
};
Expand All @@ -56,12 +56,12 @@ const HeroModels: React.FC<HeroModelsProps> = ({ onChange }) => {
<Dropdown
className={styles.combobox}
id={selectId}
defaultSelectedOptions={[getDefaultModel().id]}
defaultValue={getDefaultModel().name}
defaultSelectedOptions={[getDefaultModel(provider).id]}
defaultValue={getDefaultModel(provider).name}
onActiveOptionChange={handleChange}
onChange={handleChange}
>
{config.models.map((option: AIModel) => (
{provider.models.map((option: AIModel) => (
<Option value={option.id} key={option.id}>
{option.name}
</Option>
Expand Down
58 changes: 43 additions & 15 deletions src/config.json
Original file line number Diff line number Diff line change
@@ -1,19 +1,47 @@
{
"models": [
{
"id": "llama-3.1-8b-instant",
"name": "Llama 3.1 (8B) - Instant",
"default": false
},
{
"id": "llama-3.2-3b-preview",
"name": "Llama 3.2 (3B)",
"default": false
},
{
"id": "llama-3.2-90b-text-preview",
"name": "Llama 3.2 (90B)",
"default": true
"providers": [
{
"default": true,
"name": "Groq",
"baseUrl": "https://api.groq.com",
"basePath": "/openai/v1",
"apiKey": "groqKey",
"models": [
{
"id": "llama-3.1-8b-instant",
"name": "Llama 3.1 (8B) - Instant",
"default": false
},
{
"id": "llama-3.2-3b-preview",
"name": "Llama 3.2 (3B)",
"default": false
},
{
"id": "llama-3.2-90b-text-preview",
"name": "Llama 3.2 (90B)",
"default": true
}
]
},
{
"default": false,
"name": "SambaNovaAI",
"baseUrl": "https://api.sambanova.ai",
"basePath": "/v1",
"apiKey": "sambanovaKey",
"models": [
{
"id": "Meta-Llama-3.1-405B-Instruct",
"name": "Llama 3.1 (405B) - Instruct",
"default": false
},
{
"id": "Meta-Llama-3.1-8B-Instruct",
"name": "Llama 3.1 (8B) - Instant",
"default": true
}
]
}
],
"tests": [
Expand Down

0 comments on commit d7ecfa2

Please sign in to comment.