Skip to content

Commit

Permalink
Merge pull request #37 from MorpheusAIs/development
Browse files Browse the repository at this point in the history
Merge Development branch (0.0.6) to main branch
  • Loading branch information
betterbrand authored Feb 28, 2024
2 parents 674f985 + 03bbcf8 commit 6469425
Show file tree
Hide file tree
Showing 15 changed files with 529 additions and 234 deletions.
5 changes: 4 additions & 1 deletion .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
yarn run pretty
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

npx lint-staged
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@ Other run, test, and build scripts can be found in package.json

Please visit MOR.software to sign up as a developer to be rewarded for your merged contributions. Submit an MRC to get support for feature and improvement ideas.


MOR.software is also the place to build, submit, deplloy, and manage all of your Smart Agents.
49 changes: 17 additions & 32 deletions forge.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { AutoUnpackNativesPlugin } from '@electron-forge/plugin-auto-unpack-nati
import { WebpackPlugin } from '@electron-forge/plugin-webpack';
import { PublisherGithub } from '@electron-forge/publisher-github';
import fs from 'fs';
import path from 'path';
import { exec } from 'child_process';

import { mainConfig, mainDevConfig } from './webpack.main.config';
Expand All @@ -18,7 +17,7 @@ const config: ForgeConfig = {
packagerConfig: {
asar: true,
name: 'morpheus',
extraResource: ['./src/executables/'],
extraResource: ['./executables/'],
icon: 'src/frontend/assets/images/circle-mor-logo',
osxSign: {
identity: process.env.APPLE_DEVELOPER_ID,
Expand All @@ -31,40 +30,34 @@ const config: ForgeConfig = {
...(process.env.APPLE_ID &&
process.env.APPLE_ID_PASSWORD &&
process.env.APPLE_TEAM_ID && {
osxNotarize: {
appleId: process.env.APPLE_ID,
appleIdPassword: process.env.APPLE_ID_PASSWORD,
teamId: process.env.APPLE_TEAM_ID,
},
}),
osxNotarize: {
appleId: process.env.APPLE_ID,
appleIdPassword: process.env.APPLE_ID_PASSWORD,
teamId: process.env.APPLE_TEAM_ID,
},
}),
},
hooks: {
postPackage: async (_, { platform, outputPaths }) => {
prePackage: async (_, platform) => {
const platformFile =
platform === 'darwin'
? 'ollama-darwin'
: platform === 'win32'
? 'ollama.exe'
: 'ollama-linux';

const outputResourceFolder = `${outputPaths[0]}${platform === 'darwin' ? '/morpheus.app/Contents' : ''}/resources/executables/`;

fs.readdir(outputResourceFolder, (err, files) => {
if (err) {
throw err;
}
const filePath = `src/executables/${platformFile}`;

files.forEach((file) => {
const localPath = path.join(outputResourceFolder, file);
platform !== 'win32'
? exec(`chmod +x ${filePath}`)
: fs.chmodSync(filePath, 755);

if (file !== platformFile) {
//fs.unlinkSync(localPath);
} else {
platform !== 'win32' ? exec(`chmod +x ${localPath}`) : fs.chmodSync(localPath, 755);
}
});
});
fs.mkdirSync('executables');
fs.copyFileSync(filePath, `executables/${platformFile}`);
},
postPackage: async () => {
fs.rmSync('executables', { recursive: true, force: true });
}
},
rebuildConfig: {},
makers: [
Expand Down Expand Up @@ -94,14 +87,6 @@ const config: ForgeConfig = {
},
},
},
// contents: [
// {
// x: 410,
// y: 220,
// type: 'link',
// path: '/Applications',
// },
// ],
}),
],
publishers: [
Expand Down
6 changes: 6 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@
"singleQuote": true,
"printWidth": 100
},
"lint-staged": {
"src/**/*.{js,jsx,ts,tsx,json,css}": [
"prettier --write"
]
},
"husky": {
"hooks": {
"pre-commit": "yarn run pretty"
Expand Down Expand Up @@ -64,6 +69,7 @@
"eslint-plugin-import": "^2.25.0",
"fork-ts-checker-webpack-plugin": "^7.2.13",
"husky": "^9.0.5",
"lint-staged": "^15.2.2",
"node-loader": "^2.0.0",
"prettier": "^3.2.4",
"style-loader": "^3.0.0",
Expand Down
6 changes: 4 additions & 2 deletions src/backend/services/ollama.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,6 @@ export const getOllamaExecutableAndAppDataPath = (
};

export const askOllama = async (model: string, message: string) => {
console.log("I AM HERE")
return await ollama.chat({
model,
messages: [
Expand All @@ -153,7 +152,7 @@ export const askOllama = async (model: string, message: string) => {
},
{
role: 'user',
content: `Now answer the following question in a valid formatted JSON object without comments with both the response and transaction fields deduced from the users question. If the user's question does not initiate a transaction, let the transaction be an empty object. Adhere strictly to JSON syntax without comments. Question: ${message}. Response:`,
content: `Answer the following query in a valid formatted JSON object without comments with both the response and action fields deduced from the user's question. Adhere strictly to JSON syntax without comments. Query: ${message}. Response: { "response":`,
},
],
});
Expand All @@ -162,6 +161,9 @@ export const askOllama = async (model: string, message: string) => {
export const getOrPullModel = async (model: string) => {
await installModelWithStatus(model);

// init the model on pull to load into memory
await ollama.chat({ model });

return findModel(model);
};

Expand Down
196 changes: 109 additions & 87 deletions src/backend/services/prompts.ts
Original file line number Diff line number Diff line change
@@ -1,98 +1,120 @@
export const MOR_PROMPT =
`###System:
You are MORPHEUS, an AI assistant, but you prefer to be called a SmartAgent. You respond to any question users may have and assist them in sending transactions
with metamask by creating a valid transaction object.
export const MOR_PROMPT = `###System:
You are MORPHEUS, but you prefer to be called a SmartAgent. You are designed to assist users with MetaMask transactions and queries in a consistent JSON format. You handle bad queries gracefully as detailed in the "Bad Queries" section. Your responses should always contain a "response" field for textual feedback
and an "action" field for transaction details. There are multiple action types, as detailed in the "Action Types" section.
###Response Format:
All responses must follow this JSON structure:
{
"response": "Textual feedback here.",
"action": {
// Action details or an empty object
}
}
Respond only in valid JSON without any comments. If the user is initiating an action, create a valid transaction JSON object from their query. If the user is not initiating an action, the "action" field should be an empty object. The object should be structured based on the type of action they wish to initiate. Keep the "response" field short, using 3 sentences maximum.
###Action Types:
1. **Transfer**: For users wanting to transfer ETH. The user's input should provide the target address and ETH amount.
- **Format**:
{
"response": "Textual feedback here.",
"action": {
"type": "Transfer",
"targetAddress": "address",
"ethAmount": "amount"
}
}
2. **Balance Inquiry**: For users inquiring about their ETH balance. For all Balance inquiries, the "action" field should contain only the "type" key with the value "Balance". The "response" field should be set to empty.
- **Format**:
{
"response": "",
"action": {
"type": "Balance"
}
}
3. **Address Inquiry**: For users inquiring about their wallet address. For all Address inquiries, the "action" field should contain only the "type" key with the value "Address". The "response" field should be set to empty.
- **Format**:
{
"response": "",
"action": {
"type": "Address"
}
}
###Error Handling:
For actions requiring more information (e.g., missing ETH amount for transfers), respond with a request for the necessary details:
{
"response": "Request for more information goes here",
"action": {}
}
Keep your response short, using 2 or 3 sentences maximum.
Respond in a valid JSON without comments to be consumed by an application following this pattern:
{"response", "your response goes here", "transaction", "user transaction object goes here"}.
Only respond with a JSON object without any comments, NEVER provide any text outside of the json. Your respond only in a valid JSON.
If the user wants to initate a transaction with their question, create a valid transaction JSON object from the information in their question. If the user is not initating a
transaction with their question let the transaction field be an empty object. Structure the object based off the type of transaction they want to intiate.
For Transfer transactions create a JSON transaction object without any comments even on missing data following this pattern:
{"type": "Transfer":, "targetAddress": "target address goes here", "ethAmount": "amount of eth to transfer goes here"}
For Balance transactions create a transaction object following this pattern:
{"type": "Balance"}
If there are comments in the format, please remove them before returning the JSON object.
Here are examples on how to create the transaction object from the question:
###Examples:
Example 1: User is initiating a transfer transaction with their question.
Question: "transfer 43 eth to 0x223738a369F0804c091e13740D26D1269294bc1b",
Response: "{
"response": "Of course! The transaction details are prepared for you. Please double-check the parameters before confirming on Metamask.",
"transaction": {
"type": "transfer",
"targetAddress": "0x223738a369F0804c091e13740D26D1269294bc1b",
"ethAmount": "43"
}
}"
Example 2: User is intiating a balance transaction with their question
Question: "balance?"
Response: "{
"response": "",
"transaction": {
"type": "Balance"
}
}"
Example 3: User is intiating a balance transaction with their question
Question: "Hey Morpheus, whats my balance?"
Response: "{
"response": "",
"transaction": {
"type": "Balance"
}
}"
Example 3: User is intiating a balance transaction with their question
Question: "how much eth do i have?"
Response: "{
"response": "",
"transaction": {
"type": "Balance"
}
}"
Example 4: question does not initiate a transaction, let the transaction be an empty object.
Question: "Why is the sky blue"
Response: "{
"response": "The sky is blue because of a thing called Rayleigh scattering. When sunlight enters the Earth\'s atmosphere, it hits air and other tiny particles. This light is made of many colors. Blue light scatters more because it travels as shorter, smaller waves. So, when we look up, we see more blue light than other colors.",
"transaction": {}
}"
Example 5: question does not initiate a transaction, let the transaction be an empty object..
Question: "What is stETH"
Response: "{
"response": "stETH stands for staked Ether. It's a type of cryptocurrency. When people stake their Ether (ETH) in a blockchain network to support it, they get stETH in return. This shows they have ETH locked up, and they can still use stETH in other crypto activities while earning rewards.",
"transaction": {}
// Transfer Action
- **Transfer actions**:
- Question: "transfer 2 eth to 0x123..."
- Response:
{
"response": "Transfer prepared. Please confirm the details in MetaMask.",
"action": {"type": "Transfer", "targetAddress": "0x123...", "ethAmount": "2"}
}
// Balance Inquiries
- **Balance inquiry**:
- Questions: "What's my balance?", "Could you tell me my current balance, please?", "how much eth I got?", "Hey Morpheus, can you show me my balance now?", "I need to see my ETH balance, can you help?", "balance?"
- Response for all:
{
"response": "",
"action": {"type": "Balance"}
}
// Address Inquiries
- **Address inquiry**:
- Question: "What is my wallet address?", "What is my public Eth address?", "Can you show me my wallet address?", "Hey Morpheus, can you tell me my wallet address?"
- Response for all:
{
"response": "",
"action": {"type": "Address"}
}
// Insufficient Information for Transfer
- **Insufficient info for transfer**:
- Question: "I want to transfer ETH."
- Response:
{
"response": "Please provide the ETH amount and the target address for the transfer.",
"action": {}
}
- **Bad Query**:
- Questions: "please explain", "why does", "who is"
- Response:
{
"response": "Sorry! I dont think I understand, what would you like me to explain?",
"action": {}
}
Example 6: sufficient information in the question to create a valid transaction object. If the question does not provide enough information for a transaction, let the transaction field be an empty object.
Question: "transfer"
Response: "{
"response": "I can certainly help you transfer ethereum, However, i needthe eth amount and target address",
"transaction": {}
}
For Transfer transactions, ensure that there is sufficient information in the question to create a valid transaction object. If the question does not provide enough information for a transaction, do not include a transaction object in the response.
// Non-action Queries
- **Non-action query (e.g., general question)**:
- Question: "What is stETH?"
- Response:
{
"response": "stETH stands for staked Ether...",
"action": {}
}
`;

export const errorHandling = `If a question is initiating a buy or transfer transaction and the user doesn't specify an amount in ETH. Gently decline to send the transaction
and request the amount to buy or transfer (depending on their transaction type) in ethereum.
export const errorHandling = `###Error Handling:
- For buy or transfer actions without a specified ETH amount, request the missing details.
- For sell actions without a specified token amount, request the missing details.
- Never include comments within the JSON objects returned.
- Plan for detailed error messages for unsupported or incomplete action requests to guide users effectively.`;

If a question is initiating a sell transaction and the user doesn't specify an amount in tokens. Gently decline to send the transaction
and request the amount to sell in tokens.
In your response, if you do generate a transaction JSON object, never include any comments in the JSON format you return back.
`;
//TODO: allow for staking MOR and swap tokens
//TODO: use RAG to include a database to tokenAddresses and symbols
//TODO: include chat history
//TODO: include error handling in prompt
//TODO: include error handling in prompt
Binary file added src/executables/ollama.exe
Binary file not shown.
1 change: 1 addition & 0 deletions src/frontend/constants.ts

Large diffs are not rendered by default.

12 changes: 9 additions & 3 deletions src/frontend/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,13 @@ import { updateQrCode } from './helpers';
import ThemeProvider from './theme/theme-provider';
import GlobalStyle from './theme/index';
import './index.css';

// context
import { AIMessagesProvider } from './contexts';

// constants
import { LOGO_METAMASK_BASE64 } from './constants';

// root
const rootElement = document.querySelector('#root') as Element;
const root = createRoot(rootElement);
Expand Down Expand Up @@ -73,7 +78,7 @@ const AppRoot = () => {

return;
} else {
console.error(`Something went wrong with pulling model ${'llam2'}`);
console.error(`Something went wrong with pulling model ${'llama2'}`);
}
}

Expand Down Expand Up @@ -104,8 +109,9 @@ const AppRoot = () => {
enabled: true,
},
dappMetadata: {
name: 'MorpheusAI SubMod',
url: window.location.host,
name: 'Morpheus Node',
url: 'https://mor.org',
base64Icon: LOGO_METAMASK_BASE64,
},
modals: {
install: ({ link }) => {
Expand Down
Loading

0 comments on commit 6469425

Please sign in to comment.