Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Predictions #2

Merged
merged 32 commits into from
Feb 4, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
22aa8f0
feat: initialize prediction plugin
nicky-ru Jan 17, 2025
508f2c0
feat: enable smart contract interaction
nicky-ru Jan 17, 2025
237b4fc
feat: add prediction resolution and active prediction retrieval funct…
nicky-ru Jan 18, 2025
6f7ce23
refactor: standardize response formatting and model class usage acros…
nicky-ru Jan 24, 2025
a7e8523
refactor: update fact evaluator response formatting and console logging
nicky-ru Jan 28, 2025
d2f17aa
refactor: update docker-compose configuration for simplified image de…
nicky-ru Jan 28, 2025
c597010
refactor: disable voice event handling in Discord client
nicky-ru Jan 28, 2025
4e44005
refactor: optimize Telegram message processing and UUID generation
nicky-ru Jan 28, 2025
17fb34f
fix: improve memory logging for duplicate memory detection
nicky-ru Jan 28, 2025
1edf4ba
refactor: improve retry mechanism for generation functions
nicky-ru Jan 28, 2025
c3ee197
Merge branch 'bino-dev' into predictions
nicky-ru Jan 28, 2025
0ed6aab
chore: update dependencies and remove unused plugin references
nicky-ru Jan 28, 2025
b013287
chore: remove Mistral model support from generation functions
nicky-ru Jan 28, 2025
aa135b0
feat: introduce PredictionResolver service for automated prediction r…
nicky-ru Jan 28, 2025
687f6df
feat: add prediction evaluator and blockchain interaction for DePIN p…
nicky-ru Jan 28, 2025
1d9b8ef
feat: add network support for IoTeX prediction contracts
nicky-ru Jan 28, 2025
2f8a057
feat: add ERC20 and prediction contract ABIs to DePIN plugin
nicky-ru Jan 28, 2025
4e07d38
feat: add placeBet function for blockchain prediction interactions
nicky-ru Jan 28, 2025
8a9ee1a
feat: add listPredictions action for retrieving and displaying active…
nicky-ru Jan 28, 2025
8cbb470
feat: add prepareBet and placeBet actions for blockchain prediction b…
nicky-ru Jan 28, 2025
10afbd3
fix: update prediction evaluation to use composed state and correct r…
nicky-ru Jan 29, 2025
b868e7e
refactor: simplify prepareBet action and blockchain allowance generation
nicky-ru Jan 29, 2025
6125d0e
refactor: improve JSON response formatting and parsing guidelines
nicky-ru Jan 29, 2025
8ac39f9
chore: update dependencies and lock file
nicky-ru Jan 29, 2025
5f54b5c
refactor: update model class and debug logging
nicky-ru Jan 29, 2025
e3d8b38
refactor: enhance prediction actions and blockchain interactions
nicky-ru Jan 29, 2025
d5f536d
refactor: centralize network configuration in blockchain helpers
nicky-ru Jan 31, 2025
8e37d6e
refactor: remove unused network retrieval in prepareBet action
nicky-ru Jan 31, 2025
4a18da6
feat: add prediction count validation in prediction evaluator
nicky-ru Jan 31, 2025
2e43fca
feat: add blockchain contract ABIs and Solidity contract for predicti…
nicky-ru Jan 31, 2025
47ffa45
docs: update README with comprehensive prediction market and QuickSil…
nicky-ru Jan 31, 2025
14528bf
refactor: replace SENTAI_ERC20 with PREDICTION_TOKEN in blockchain in…
nicky-ru Jan 31, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 10 additions & 5 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
services:
tee:
image: bino:latest
command: ["pnpm", "start", "--character=${CHARACTER_FILE}"]
build:
context: .
dockerfile: Dockerfile
stdin_open: true
tty: true
volumes:
- /var/run/tappd.sock:/var/run/tappd.sock
- ./characters:/app/characters
# If we want to mount a local directory into the container
# - type: bind
# source: /root/iotex2-docs
# target: /app/characters/knowledge/iotex2-docs
# bind:
# create_host_path: true
env_file:
- .env
environment:
- CHARACTER_FILE=${CHARACTER_FILE}
- NODE_OPTIONS=--max-old-space-size=8192
- PORT=${PORT}
ports:
- "3000"
restart: always
- "${PORT}:3000"
restart: always
49 changes: 47 additions & 2 deletions packages/adapter-postgres/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { v4 } from "uuid";

// Import the entire module as default
import pg, { PoolConfig} from "pg";
import pg, { PoolConfig } from "pg";
type Pool = pg.Pool;

import {
Expand All @@ -11,6 +11,7 @@ import {
EmbeddingProvider,
GoalStatus,
Participant,
Prediction,
RAGKnowledgeItem,
elizaLogger,
getEmbeddingConfig,
Expand Down Expand Up @@ -1783,6 +1784,50 @@ export class PostgresDatabaseAdapter
]
);
}

async createPrediction(prediction: Prediction): Promise<void> {
await this.pool.query(
`INSERT INTO predictions (id, creator, statement, deadline, contract_address, status, smartcontract_id) VALUES ($1, $2, $3, $4, $5, $6, $7)`,
[
prediction.id,
prediction.creator,
prediction.statement,
prediction.deadline,
prediction.contract_address,
prediction.status,
prediction.smartcontract_id,
]
);
}

async getPredictions(params: {
status: "OPEN" | "RESOLVED" | "CLOSED";
}): Promise<Prediction[]> {
const { rows } = await this.pool.query(
`SELECT * FROM predictions WHERE "status" = $1`,
[params.status]
);
return rows;
}

async getReadyActivePredictions(): Promise<Prediction[]> {
const currentTime = new Date();
const { rows } = await this.pool.query(
`SELECT * FROM predictions WHERE "status" = 'OPEN' AND "deadline" < $1`,
[currentTime]
);
return rows;
}

async resolvePrediction(
predictionId: string,
outcome: boolean
): Promise<void> {
await this.pool.query(
`UPDATE predictions SET "status" = 'RESOLVED', "outcome" = $2 WHERE "id" = $1`,
[predictionId, outcome]
);
}
}

export default PostgresDatabaseAdapter;
export default PostgresDatabaseAdapter;
4 changes: 2 additions & 2 deletions packages/client-auto/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Client, IAgentRuntime, elizaLogger } from "@elizaos/core";
import { Client, elizaLogger, IAgentRuntime } from "@elizaos/core";

export class AutoClient {
interval: NodeJS.Timeout;
Expand All @@ -10,7 +10,7 @@ export class AutoClient {
// start a loop that runs every x seconds
this.interval = setInterval(
async () => {
elizaLogger.log("running auto client...");
elizaLogger.debug("running auto client...");
},
60 * 60 * 1000
); // 1 hour in milliseconds
Expand Down
4 changes: 2 additions & 2 deletions packages/client-direct/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ export class DirectClient {
const response = await generateMessageResponse({
runtime: runtime,
context,
modelClass: ModelClass.LARGE,
modelClass: ModelClass.SMALL,
});

if (!response) {
Expand Down Expand Up @@ -519,7 +519,7 @@ export class DirectClient {
const response = await generateMessageResponse({
runtime: runtime,
context,
modelClass: ModelClass.LARGE,
modelClass: ModelClass.SMALL,
});

// save response to memory
Expand Down
9 changes: 5 additions & 4 deletions packages/client-discord/src/actions/chat_with_attachments.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { composeContext, getModelSettings } from "@elizaos/core";
import { composeContext, getModelSettings, parseTagContent } from "@elizaos/core";
import { generateText, trimTokens } from "@elizaos/core";
import { models } from "@elizaos/core";
import { parseJSONObjectFromText } from "@elizaos/core";
Expand Down Expand Up @@ -32,12 +32,12 @@ The "objective" is a detailed description of what the user wants to summarize ba
The "attachmentIds" is an array of attachment IDs that the user wants to summarize. If not specified, default to including all attachments from the conversation.

Your response must be formatted as a JSON block with this structure:
\`\`\`json
<response>
{
"objective": "<What the user wants to summarize>",
"attachmentIds": ["<Attachment ID 1>", "<Attachment ID 2>", ...]
}
\`\`\`
</response>
`;

const getAttachmentIds = async (
Expand All @@ -60,7 +60,8 @@ const getAttachmentIds = async (
});
console.log("response", response);
// try parsing to a json object
const parsedResponse = parseJSONObjectFromText(response) as {
const extractedResponse = parseTagContent(response, "response");
const parsedResponse = parseJSONObjectFromText(extractedResponse) as {
objective: string;
attachmentIds: string[];
} | null;
Expand Down
9 changes: 5 additions & 4 deletions packages/client-discord/src/actions/download_media.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import path from "path";
import { composeContext } from "@elizaos/core";
import { composeContext, parseTagContent } from "@elizaos/core";
import { parseJSONObjectFromText } from "@elizaos/core";
import {
Action,
Expand All @@ -22,11 +22,11 @@ export const mediaUrlTemplate = `# Messages we are searching for a media URL
The "mediaUrl" is the URL of the media file that the user wants downloaded. If not specified, return null.

Your response must be formatted as a JSON block with this structure:
\`\`\`json
<response>
{
"mediaUrl": "<Media URL>"
}
\`\`\`
</response>
`;

const getMediaUrl = async (
Expand All @@ -50,7 +50,8 @@ const getMediaUrl = async (
modelClass: ModelClass.SMALL,
});

const parsedResponse = parseJSONObjectFromText(response) as {
const extractedResponse = parseTagContent(response, "response");
const parsedResponse = parseJSONObjectFromText(extractedResponse) as {
mediaUrl: string;
} | null;

Expand Down
9 changes: 5 additions & 4 deletions packages/client-discord/src/actions/summarize_conversation.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { composeContext, getModelSettings } from "@elizaos/core";
import { composeContext, getModelSettings, parseTagContent } from "@elizaos/core";
import { generateText, splitChunks, trimTokens } from "@elizaos/core";
import { getActorDetails } from "@elizaos/core";
import { parseJSONObjectFromText } from "@elizaos/core";
Expand Down Expand Up @@ -33,13 +33,13 @@ The "start" and "end" are the range of dates that the user wants to summarize, r
If you aren't sure, you can use a default range of "0 minutes ago" to "2 hours ago" or more. Better to err on the side of including too much than too little.

Your response must be formatted as a JSON block with this structure:
\`\`\`json
<response>
{
"objective": "<What the user wants to summarize>",
"start": "0 minutes ago",
"end": "2 hours ago"
}
\`\`\`
</response>
`;

const getDateRange = async (
Expand All @@ -62,7 +62,8 @@ const getDateRange = async (
});
console.log("response", response);
// try parsing to a json object
const parsedResponse = parseJSONObjectFromText(response) as {
const extractedResponse = parseTagContent(response, "response");
const parsedResponse = parseJSONObjectFromText(extractedResponse) as {
objective: string;
start: string | number;
end: string | number;
Expand Down
9 changes: 5 additions & 4 deletions packages/client-discord/src/actions/transcribe_media.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { composeContext } from "@elizaos/core";
import { composeContext, parseTagContent } from "@elizaos/core";
import { generateText } from "@elizaos/core";
import { parseJSONObjectFromText } from "@elizaos/core";
import {
Expand All @@ -24,10 +24,11 @@ export const mediaAttachmentIdTemplate = `# Messages we are transcribing
The "attachmentId" is the ID of the media file attachment that the user wants transcribed. If not specified, return null.

Your response must be formatted as a JSON block with this structure:
\`\`\`json
<response>
{
"attachmentId": "<Attachment ID>"
}
</response>
\`\`\`
`;

Expand All @@ -50,8 +51,8 @@ const getMediaAttachmentId = async (
modelClass: ModelClass.SMALL,
});
console.log("response", response);

const parsedResponse = parseJSONObjectFromText(response) as {
const extractedResponse = parseTagContent(response, "response");
const parsedResponse = parseJSONObjectFromText(extractedResponse) as {
attachmentId: string;
} | null;

Expand Down
8 changes: 5 additions & 3 deletions packages/client-discord/src/attachments.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { generateText, trimTokens } from "@elizaos/core";
import { generateText, parseTagContent, trimTokens } from "@elizaos/core";
import { parseJSONObjectFromText } from "@elizaos/core";
import {
IAgentRuntime,
Expand Down Expand Up @@ -28,11 +28,12 @@ async function generateSummary(
"""

Respond with a JSON object in the following format:
\`\`\`json
<response>
{
"title": "Generated Title",
"summary": "Generated summary and/or description of the text"
}
</response>
\`\`\``;

const response = await generateText({
Expand All @@ -41,7 +42,8 @@ async function generateSummary(
modelClass: ModelClass.SMALL,
});

const parsedResponse = parseJSONObjectFromText(response);
const extractedResponse = parseTagContent(response, "response");
const parsedResponse = parseJSONObjectFromText(extractedResponse);

if (parsedResponse) {
return {
Expand Down
16 changes: 8 additions & 8 deletions packages/client-discord/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,14 +93,14 @@ export class DiscordClient extends EventEmitter {
// );

// Handle voice events with the voice manager
this.client.on(
"voiceStateUpdate",
this.voiceManager.handleVoiceStateUpdate.bind(this.voiceManager)
);
this.client.on(
"userStream",
this.voiceManager.handleUserStream.bind(this.voiceManager)
);
// this.client.on(
// "voiceStateUpdate",
// this.voiceManager.handleVoiceStateUpdate.bind(this.voiceManager)
// );
// this.client.on(
// "userStream",
// this.voiceManager.handleUserStream.bind(this.voiceManager)
// );

// Handle a new message with the message manager
this.client.on(
Expand Down
20 changes: 13 additions & 7 deletions packages/client-discord/src/messages.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { composeContext, composeRandomUser } from "@elizaos/core";
import {
composeContext,
composeRandomUser,
parseTagContent,
} from "@elizaos/core";
import { generateMessageResponse, generateShouldRespond } from "@elizaos/core";
import {
Content,
Expand Down Expand Up @@ -1242,13 +1246,15 @@ export class MessageManager {
composeRandomUser(discordShouldRespondTemplate, 2),
});

const response = await generateShouldRespond({
const rawResponse = await generateShouldRespond({
runtime: this.runtime,
context: shouldRespondContext,
modelClass: ModelClass.SMALL,
});

if (response === "RESPOND") {
const parsedResponse = parseTagContent(rawResponse, "response");

if (parsedResponse === "RESPOND") {
if (channelState) {
channelState.previousContext = {
content: message.content,
Expand All @@ -1257,23 +1263,23 @@ export class MessageManager {
}

return true;
} else if (response === "IGNORE") {
} else if (parsedResponse === "IGNORE") {
return false;
} else if (response === "STOP") {
} else if (parsedResponse === "STOP") {
delete this.interestChannels[message.channelId];
return false;
} else {
console.error(
"Invalid response from response generateText:",
response
parsedResponse
);
return false;
}
}

private async _generateResponse(
message: Memory,
state: State,
_state: State,
context: string
): Promise<Content> {
const { userId, roomId } = message;
Expand Down
Loading
Loading