Skip to content

Commit

Permalink
Merge branch 'main' into kresimir/code-interpreter
Browse files Browse the repository at this point in the history
# Conflicts:
#	oracles/oracle.py
#	oracles/settings.py
  • Loading branch information
kgrofelnik committed Mar 28, 2024
2 parents 12838e9 + 1d5f8ba commit e897bef
Show file tree
Hide file tree
Showing 28 changed files with 1,174 additions and 26 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ contracts/agent/build
contracts/agent-old/build
contracts/agent2/build
arbitrum-contracts/node_modules

.DS_Store
1 change: 0 additions & 1 deletion contracts/contracts/Agent.sol
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ contract Agent {
owner = msg.sender;
oracleAddress = initialOracleAddress;
prompt = systemPrompt;
agentRunCount = 0;
}

modifier onlyOwner() {
Expand Down
71 changes: 67 additions & 4 deletions contracts/contracts/ChatGpt.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@ interface IOracle {
function createLlmCall(
uint promptId
) external returns (uint);

function createKnowledgeBaseQuery(
uint kbQueryCallbackId,
string memory cid,
string memory query,
uint32 num_documents
) external returns (uint i);
}

contract ChatGpt {
Expand All @@ -30,13 +37,14 @@ contract ChatGpt {

address private owner;
address public oracleAddress;
string public knowledgeBase;

event OracleAddressUpdated(address indexed newOracleAddress);

constructor(address initialOracleAddress) {
constructor(address initialOracleAddress, string memory knowledgeBaseCID) {
owner = msg.sender;
oracleAddress = initialOracleAddress;
chatRunsCount = 0;
knowledgeBase = knowledgeBaseCID;
}

modifier onlyOwner() {
Expand Down Expand Up @@ -67,7 +75,18 @@ contract ChatGpt {
uint currentId = chatRunsCount;
chatRunsCount = chatRunsCount + 1;

IOracle(oracleAddress).createLlmCall(currentId);
// If there is a knowledge base, create a knowledge base query
if (bytes(knowledgeBase).length > 0) {
IOracle(oracleAddress).createKnowledgeBaseQuery(
currentId,
knowledgeBase,
message,
3
);
} else {
// Otherwise, create an LLM call
IOracle(oracleAddress).createLlmCall(currentId);
}
emit ChatCreated(msg.sender, currentId);

return currentId;
Expand All @@ -91,6 +110,39 @@ contract ChatGpt {
run.messagesCount++;
}

function onOracleKnowledgeBaseQueryResponse(
uint runId,
string [] memory documents,
string memory errorMessage
) public onlyOracle {
ChatRun storage run = chatRuns[runId];
require(
keccak256(abi.encodePacked(run.messages[run.messagesCount - 1].role)) == keccak256(abi.encodePacked("user")),
"No message to add context to"
);
// Retrieve the last user message
Message storage lastMessage = run.messages[run.messagesCount - 1];

// Start with the original message content
string memory newContent = lastMessage.content;

// Append "Relevant context:\n" only if there are documents
if (documents.length > 0) {
newContent = string(abi.encodePacked(newContent, "\n\nRelevant context:\n"));
}

// Iterate through the documents and append each to the newContent
for (uint i = 0; i < documents.length; i++) {
newContent = string(abi.encodePacked(newContent, documents[i], "\n"));
}

// Finally, set the lastMessage content to the newly constructed string
lastMessage.content = newContent;

// Call LLM
IOracle(oracleAddress).createLlmCall(runId);
}

function addMessage(string memory message, uint runId) public {
ChatRun storage run = chatRuns[runId];
require(
Expand All @@ -106,7 +158,18 @@ contract ChatGpt {
newMessage.role = "user";
run.messages.push(newMessage);
run.messagesCount++;
IOracle(oracleAddress).createLlmCall(runId);
// If there is a knowledge base, create a knowledge base query
if (bytes(knowledgeBase).length > 0) {
IOracle(oracleAddress).createKnowledgeBaseQuery(
runId,
knowledgeBase,
message,
3
);
} else {
// Otherwise, create an LLM call
IOracle(oracleAddress).createLlmCall(runId);
}
}

function getMessageHistoryContents(uint chatId) public view returns (string[] memory) {
Expand Down
102 changes: 102 additions & 0 deletions contracts/contracts/ChatOracle.sol
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,12 @@ interface IOracleTypes {
uint32 promptTokens;
uint32 totalTokens;
}

struct KnowledgeBaseQueryRequest {
string cid;
string query;
uint32 num_documents;
}
}

interface IChatGpt {
Expand All @@ -107,6 +113,12 @@ interface IChatGpt {
string memory errorMessage
) external;

function onOracleKnowledgeBaseQueryResponse(
uint callbackId,
string [] memory documents,
string memory errorMessage
) external;

function getMessageHistoryContents(
uint callbackId
) external view returns (string[] memory);
Expand Down Expand Up @@ -170,6 +182,17 @@ contract ChatOracle {
mapping(uint => bool) public isFunctionProcessed;
uint public functionsCount;

mapping(uint => string) public kbIndexingRequests;
mapping(uint => string) public kbIndexingRequestErrors;
mapping(uint => bool) public isKbIndexingRequestProcessed;
mapping(string => string) public kbIndexes;
uint public kbIndexingRequestCount;

mapping(uint => IOracleTypes.KnowledgeBaseQueryRequest) public kbQueries;
mapping(uint => address) public kbQueryCallbackAddresses;
mapping(uint => uint) public kbQueryCallbackIds;
mapping(uint => bool) public isKbQueryProcessed;
uint public kbQueryCount;

address private owner;

Expand All @@ -180,6 +203,21 @@ contract ChatOracle {
address sender
);

event KnowledgeBaseIndexRequestAdded(
uint indexed id,
address sender
);

event KnowledgeBaseIndexed(
string indexed cid,
string indexed indexCid
);

event knowledgeBaseQueryAdded(
uint indexed kbQueryId,
address sender
);

constructor() {
owner = msg.sender;
promptsCount = 0;
Expand Down Expand Up @@ -360,4 +398,68 @@ contract ChatOracle {
function markGroqPromptAsProcessed(uint promptId) public onlyWhitelisted {
isPromptProcessed[promptId] = true;
}

function addKnowledgeBase(string memory cid) public {
require(bytes(kbIndexes[cid]).length == 0, "Index already set for this CID");
uint kbIndexingRequestId = kbIndexingRequestCount;
kbIndexingRequests[kbIndexingRequestId] = cid;
kbIndexingRequestCount++;
emit KnowledgeBaseIndexRequestAdded(kbIndexingRequestId, msg.sender);
}

function addKnowledgeBaseIndex(uint kbIndexingRequestId, string memory indexCid, string memory error) public onlyWhitelisted {
require(!isKbIndexingRequestProcessed[kbIndexingRequestId], "Indexing request already processed");
kbIndexes[kbIndexingRequests[kbIndexingRequestId]] = indexCid;
kbIndexingRequestErrors[kbIndexingRequestId] = error;
isKbIndexingRequestProcessed[kbIndexingRequestId] = true;
emit KnowledgeBaseIndexed(kbIndexingRequests[kbIndexingRequestId], indexCid);
}

function markKnowledgeBaseAsProcessed(uint kbIndexingRequestId) public onlyWhitelisted {
isKbIndexingRequestProcessed[kbIndexingRequestId] = true;
}

function createKnowledgeBaseQuery(
uint kbQueryCallbackId,
string memory cid,
string memory query,
uint32 num_documents
) public returns (uint i) {
require(bytes(kbIndexes[cid]).length > 0, "Index not available for this CID");
require(bytes(query).length > 0, "Query cannot be empty");
require(num_documents > 0, "Number of documents should be greater than 0");
uint kbQueryId = kbQueryCount;
kbQueries[kbQueryId].cid = cid;
kbQueries[kbQueryId].query = query;
kbQueries[kbQueryId].num_documents = num_documents;
kbQueryCallbackIds[kbQueryId] = kbQueryCallbackId;

kbQueryCallbackAddresses[kbQueryId] = msg.sender;
isKbQueryProcessed[kbQueryId] = false;

kbQueryCount++;

emit knowledgeBaseQueryAdded(kbQueryId, msg.sender);

return kbQueryId;
}

function addKnowledgeBaseQueryResponse(
uint kbQueryId,
uint kbQueryCallbackId,
string [] memory documents,
string memory errorMessage
) public onlyWhitelisted {
require(!isKbQueryProcessed[kbQueryId], "Knowledge base query already processed");
isKbQueryProcessed[kbQueryId] = true;
IChatGpt(kbQueryCallbackAddresses[kbQueryId]).onOracleKnowledgeBaseQueryResponse(
kbQueryCallbackId,
documents,
errorMessage
);
}

function markKnowledgeBaseQueryAsProcessed(uint kbQueryId) public onlyWhitelisted {
isKbQueryProcessed[kbQueryId] = true;
}
}
14 changes: 12 additions & 2 deletions contracts/scripts/deployAll.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ async function main() {
await deployVitailik(oracleAddress);
await deployAgent(oracleAddress);
console.log()

for (let contractName of ["ChatGpt", "OpenAiChatGpt", "GroqChatGpt"]) {
await deployChatGptWithKnowledgeBase("ChatGpt", oracleAddress, "");
for (let contractName of ["OpenAiChatGpt", "GroqChatGpt"]) {
await deployChatGpt(contractName, oracleAddress)
}
}
Expand Down Expand Up @@ -86,6 +86,16 @@ async function deployChatGpt(contractName: string, oracleAddress: string) {
);
}

async function deployChatGptWithKnowledgeBase(contractName: string, oracleAddress: string, knowledgeBaseCID: string) {
const agent = await ethers.deployContract(contractName, [oracleAddress, knowledgeBaseCID], {});

await agent.waitForDeployment();

console.log(
`${contractName} deployed to ${agent.target} with knowledge base "${knowledgeBaseCID}"`
);
}


// We recommend this pattern to be able to use async/await everywhere
// and properly handle errors.
Expand Down
2 changes: 1 addition & 1 deletion contracts/test/ChatGpt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ describe("ChatGpt", function () {
const oracle = await Oracle.deploy();

const ChatGpt = await ethers.getContractFactory("ChatGpt");
const chatGpt = await ChatGpt.deploy("0x0000000000000000000000000000000000000000");
const chatGpt = await ChatGpt.deploy("0x0000000000000000000000000000000000000000", "");

return {chatGpt, oracle, owner, allSigners};
}
Expand Down
Loading

0 comments on commit e897bef

Please sign in to comment.