Skip to content

Commit

Permalink
Merge conflicts
Browse files Browse the repository at this point in the history
  • Loading branch information
ferranbt committed Feb 14, 2024
2 parents e8f947c + 8fb650d commit 5550853
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 1 deletion.
4 changes: 3 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:

- name: Run suave
run: |
suave-geth --suave.dev &
suave-geth --suave.dev --suave.eth.external-whitelist='*' &
- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1
Expand All @@ -30,4 +30,6 @@ jobs:
run: forge install

- name: Run tests
env:
CHATGPT_API_KEY: ${{ secrets.CHATGPT_API_KEY }}
run: forge test --ffi
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,19 +84,36 @@ contract Example {
}
```

<<<<<<< HEAD
### protocols/EthJsonRPC.sol

Helper library to interact with the Ethereum JsonRPC protocol.
=======
### protocols/ChatGPT.sol

Helper library to send completion requests to ChatGPT.
>>>>>>> main
#### Example usage

```solidity
<<<<<<< HEAD
import "suave-std/protocols/EthJsonRPC.sol";
contract Example {
function example() {
EthJsonRPC jsonrpc = new EthJsonRPC("http://...");
jsonrpc.nonce(address(this));
=======
import "suave-std/protocols/ChatGPT.sol";
contract Example {
function example() {
ChatGPT.Message[] memory messages = new ChatGPT.Message[](1);
messages[0] = ChatGPT.Message(ChatGPT.Role.User, "How do I write a Suapp with suave-std?");
chatgpt.complete(messages);
>>>>>>> main
}
}
```
Expand Down
76 changes: 76 additions & 0 deletions src/protocols/ChatGPT.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.13;

import "src/suavelib/Suave.sol";
import "solady/src/utils/JSONParserLib.sol";

contract ChatGPT {
using JSONParserLib for *;

string apiKey;

enum Role {
User,
System
}

struct Message {
Role role;
string content;
}

constructor(string memory _apiKey) {
apiKey = _apiKey;
}

// https://platform.openai.com/docs/api-reference/making-requests
function complete(Message[] memory messages) public returns (string memory) {
bytes memory body;
body = abi.encodePacked('{"model": "gpt-3.5-turbo", "messages": [');
for (uint256 i = 0; i < messages.length; i++) {
body = abi.encodePacked(
body,
'{"role": "',
messages[i].role == Role.User ? "user" : "system",
'", "content": "',
messages[i].content,
'"}'
);
if (i < messages.length - 1) {
body = abi.encodePacked(body, ",");
}
}
body = abi.encodePacked(body, '], "temperature": 0.7}');

Suave.HttpRequest memory request;
request.method = "POST";
request.url = "https://api.openai.com/v1/chat/completions";
request.headers = new string[](2);
request.headers[0] = string.concat("Authorization: Bearer ", apiKey);
request.headers[1] = "Content-Type: application/json";
request.body = body;

bytes memory output = Suave.doHTTPRequest(request);

// decode responses
JSONParserLib.Item memory item = string(output).parse();
string memory result = trimQuotes(item.at('"choices"').at(0).at('"message"').at('"content"').value());

return result;
}

function trimQuotes(string memory input) private pure returns (string memory) {
bytes memory inputBytes = bytes(input);
require(
inputBytes.length >= 2 && inputBytes[0] == '"' && inputBytes[inputBytes.length - 1] == '"', "Invalid input"
);

bytes memory result = new bytes(inputBytes.length - 2);

for (uint256 i = 1; i < inputBytes.length - 1; i++) {
result[i - 1] = inputBytes[i];
}

return string(result);
}
}
29 changes: 29 additions & 0 deletions test/protocols/ChatGPT.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import "forge-std/Test.sol";
import "src/Test.sol";
import "src/protocols/ChatGPT.sol";

contract ChatGPTTest is Test, SuaveEnabled {
function testChatGPT() public {
ChatGPT chatgpt = getChatGPT();

ChatGPT.Message[] memory messages = new ChatGPT.Message[](1);
messages[0] = ChatGPT.Message(ChatGPT.Role.User, "Say this is a test!");

string memory expected = "This is a test!";
string memory found = chatgpt.complete(messages);

assertEq(found, expected, "ChatGPT did not return the expected result");
}

function getChatGPT() public returns (ChatGPT chatgpt) {
// NOTE: tried to do it with envOr but it did not worked
try vm.envString("CHATGPT_API_KEY") returns (string memory apiKey) {
chatgpt = new ChatGPT(apiKey);
} catch {
vm.skip(true);
}
}
}

0 comments on commit 5550853

Please sign in to comment.