Skip to content

Commit

Permalink
Refactor AIPrompt and App components
Browse files Browse the repository at this point in the history
  • Loading branch information
aeltorio committed Oct 4, 2024
1 parent b73d6f0 commit 8e89d22
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 6 deletions.
9 changes: 9 additions & 0 deletions src/aipane/AIPrompt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,3 +121,12 @@ export function getProvider(providerName: string): AIProvider {
export function getModel(provider: AIProvider, modelId: string): AIModel {
return provider.models.filter((model: AIModel) => model.id === modelId)[0];
}

/**
* Retrieves the AI model from config.json for the given provider.
* @param {AIProvider} provider - The AI provider containing the model.
* @returns {AIModel} The AI model with the specified ID.
*/
export function getDefaultModel(provider: AIProvider): AIModel {
return provider.models.filter((model: AIModel) => model.default)[0];
}
2 changes: 1 addition & 1 deletion src/aipane/aipane.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export async function insertText(provider: AIProvider, model: AIModel, apiKey: s
console.log(`User: ${user}`);
console.log(`User text: \n${userText}`);
let aiText = await groqRequest(provider, model, apiKey, system, `${user}\n${userText}`);
console.log(`AI response (${model}): \n${aiText}`);
console.log(`AI provider: ${provider.name} AI model: ${model.name}: \n${aiText}`);
aiText = aiText.replace(/\n/g, "<br>");
Office.context.mailbox.item?.body.setSelectedDataAsync(
aiText,
Expand Down
13 changes: 12 additions & 1 deletion src/aipane/components/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import * as React from "react";
import { useState, useEffect } from "react";
import Header from "./Header";
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import HeroList, { HeroListItem } from "./HeroList";
import TextInsertion from "./TextInsertion";
import { makeStyles } from "@fluentui/react-components";
Expand All @@ -15,6 +16,7 @@ import HeroApiKey from "./HeroApiKey";
import HeroComboPrompts from "./HeroComboPrompts";
import HeroModels from "./HeroModels";
import { AIModel, AIProvider, getDefaultProvider, getModel } from "../AIPrompt";
import HeroProviders from "./HeroProviders";

interface AppProps {
title: string;
Expand All @@ -36,6 +38,7 @@ const App: React.FC<AppProps> = (props: AppProps) => {

// The list items are static and won't change at runtime,
// so this should be an ordinary const, not a part of state.
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const listItems: HeroListItem[] = [
{
icon: <BrainCircuit20Regular />,
Expand Down Expand Up @@ -79,6 +82,13 @@ const App: React.FC<AppProps> = (props: AppProps) => {
insertText(provider, model, apiKey, prompt, `${userText}`);
};

const handleProviderChange = (provider: AIProvider) => {
setProvider(provider);
if (!localStorage.getItem(provider.apiKey)) {
setShowApiKeyInput(true);
}
};

return (
<div className={styles.root}>
<Header logo="assets/logo-filled.png" title={props.title} message="AI emailer" />
Expand All @@ -91,7 +101,8 @@ const App: React.FC<AppProps> = (props: AppProps) => {
/>
) : (
<>
<HeroList message="Ask Llama" items={listItems} />
{/* <HeroList message="Ask Llama" items={listItems} /> */}
<HeroProviders onChange={handleProviderChange} />
<HeroModels onChange={handleModelChange} provider={provider} />
<HeroComboPrompts onChange={handlePromptChange} />
<TextInsertion insertText={handlePromptSubmit} basePrompt={""} />
Expand Down
5 changes: 1 addition & 4 deletions src/aipane/components/HeroModels.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,14 @@
import * as React from "react";
import { Dropdown, Label, makeStyles, Option, useId } from "@fluentui/react-components";
import { useState, useEffect } from "react";
import { type AIModel, type AIProvider } from "../AIPrompt";
import { getDefaultModel, type AIModel, type AIProvider } from "../AIPrompt";

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

function getDefaultModel(provider: AIProvider): AIModel {
return provider.models.filter((model: AIModel) => model.default)[0];
}
const useStyles = makeStyles({
root: {
// Stack the label above the field
Expand Down
70 changes: 70 additions & 0 deletions src/aipane/components/HeroProviders.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
=========================================================
* © 2024 Ronan LE MEILLAT for SCTG Development
=========================================================
*/
import * as React from "react";
import { Dropdown, Label, makeStyles, Option, useId } from "@fluentui/react-components";
import { useState, useEffect } from "react";
import { getDefaultProvider, getProvider, type AIProvider } from "../AIPrompt";
import config from "../../config.json";

interface HeroProvidersProps {
onChange: (provider: AIProvider) => void;
}

const useStyles = makeStyles({
root: {
// Stack the label above the field
display: "flex",
flexDirection: "column",
// Use 2px gap below the label (per the design system)
gap: "2px",
margin: "10px",
},
combobox: {
marginTop: "20px",
marginBottom: "20px",
},
});

const HeroProviders: React.FC<HeroProvidersProps> = ({ onChange }) => {
const styles = useStyles();
const selectId = useId("select");
const [selectedValue, setSelectedValue] = useState<string>(getDefaultProvider().name);

const handleChange = (event: React.FormEvent<HTMLButtonElement>, option?: any) => {
event.preventDefault();
const newValue = option.nextOption?.value || getDefaultProvider().name;
setSelectedValue(newValue);
onChange(getProvider(newValue));
};

useEffect(() => {
onChange(getProvider(selectedValue));
}, [selectedValue]);

return (
<div className={styles.root}>
<Label htmlFor={selectId} size="large">
Provider
</Label>
<Dropdown
className={styles.combobox}
id={selectId}
defaultSelectedOptions={[getDefaultProvider().name]}
defaultValue={getDefaultProvider().name}
onActiveOptionChange={handleChange}
onChange={handleChange}
>
{config.providers.map((option: AIProvider) => (
<Option value={option.name} key={option.name}>
{option.name}
</Option>
))}
</Dropdown>
</div>
);
};

export default HeroProviders;

0 comments on commit 8e89d22

Please sign in to comment.