You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Fack answers frequently asked questions using Generative AI.
Here is an example:
Use Cases
At Salesforce, we use fack for internal Q&A. We feed documents and summarized slack threads to fack.
In some channels, we see up to 40% of our support requests receive helpful answers from fack.
We are experiementing with other use cases like:
Improving incident resolution by quickly finding suggested solutions
Translating between query languages
Almost any RAG-based solution can be quickly implmented in fack.
Why is it Called Fack?
The term FAQ, or Frequently Asked Questions, is often pronounced fack.
Inspiration
Fack is built on the principles outlined by OpenAI for question/answer applications in documents like:
Reuse your documents across multiple systems.
Need a Q/A interface? Done. Need to provide answers in a chat bot? Done.
Shared AI Knowledge
Working with LLMs is deceptively complex.
Vector embeddings, token counting, effective prompting all require thought to make effective use of LLMs.
By having a shared service, you can have one service to manage retrieval-augmented search and ask queries.
Deduplication
When managing thousands of documents, managing documents is difficult. Are there duplicates? What are the groups of documents?
Document Grouping
All documents are not equal. You have different groups within your company and organization. Different teams need to manage their documents.
Visibilty may be an issue.
Principles
API first. The end user interactions will likely happen through other bots and applications. So, the service should be API first.
Multi-tenant. Different teams should be able to share the same app, without mixing their data.
Design
Data Flow
Why Search is Better than Fine-tuning
The OpenAI doc outlines the reasons why search/retrieval is typically better than fine-tuning.
"Fine-tuning is better suited to teaching specialized tasks or styles, and is less reliable for factual recall."
Search/retrival enables more reliable source citation. We can provide specific documents with urls/names to the GPT and require references to the documents used for answering the question. In fine-tuning, the original source is most likely lost or unavailable.
Developers
Requirements
Rails 7
Ruby 3+
Postgres with pg_vector support
Environment Variables
Required Variables
Variable
Description
SALESFORCE_CONNECT_ORG_URL
Salesforce organization URL for Einstein integration
SALESFORCE_CONNECT_CLIENT_ID
Salesforce connected app client ID
SALESFORCE_CONNECT_CLIENT_SECRET
Salesforce connected app client secret
SALESFORCE_CONNECT_USERNAME
Salesforce username for Einstein integration
SALESFORCE_CONNECT_PASSWORD
Salesforce password for Einstein integration
CONFLUENCE_TOKEN
Authentication token for Confluence API
CONFLUENCE_URL
Base URL for Confluence API
QUIP_TOKEN
Authentication token for Quip API
SLACK_BOT_TOKEN
Bot token for Slack integration
SLACK_SIGNING_SECRET
Secret for verifying Slack requests
SLACK_BASE_URL
Base URL for Slack workspace
PAGERDUTY_API_TOKEN
API token for PagerDuty integration
GOOGLE_CLIENT_ID
OAuth client ID for Google authentication
GOOGLE_CLIENT_SECRET
OAuth client secret for Google authentication
TEST_PASSWORD
Password for test user (8+ chars, number, uppercase, special char)
Optional Variables
Variable
Description
Default
MAX_PROMPT_DOC_TOKENS
Max number of document tokens to send to GPT prompt
Set TEST_PASSWORD to an 8+ character string with a number, uppercase letter and special character. '2Testai!' as an example.
Create a .env file in the root directory. Provide these variables.
# LLM AUTH. You need to provide an OpenAI Key or a Salesforce Einstein Org
## OpenAI key from https://platform.openai.com/account/api-keys
OPENAI_API_KEY=<openai token>
## OR Salesforce Einstein credentials from your Org
SALESFORCE_CONNECT_ORG_URL=
SALESFORCE_CONNECT_CLIENT_ID=
SALESFORCE_CONNECT_CLIENT_SECRET=
SALESFORCE_CONNECT_USERNAME=
SALESFORCE_CONNECT_PASSWORD=
# i.e. https://fack.yourdomain.com or http://localhost:3000 Used to generate URLs in the answers.
ROOT_URL=
## SAML/SSO Metadata URL (OPTIONAL)
SSO_METADATA_URL=
## Max number of document tokens to send to the GPT prompt. (OPTIONAL)
MAX_PROMPT_DOC_TOKENS=
## Max tokens to send in the prompt (OPTIONAL, DEFAULT 10,000)
EGPT_MAX_TOKENS=
## Which OpenAI model to use. (OPTIONAL)
EGPT_GEN_MODEL=
## Disable Password Login if you have SSO enabled. (OPTIONAL)
DISABLE_PASSWORD_LOGIN=<true/false>
Open a new terminal and start the Background job for AI Calls
rake jobs:work
You should see:
[Worker(host:host.something.com pid:89737)] Starting job worker
This page allows you to create or edit a library entry, providing key details like the name of the library, its source URL, and the owner of the library. Here's how it works:
Library Name:
Enter the name of the library in the provided text box. This could be the subject or title of the library, like "Data Science Resources."
Source URL:
Provide the URL for the source of this library. This could be a link to the main website, document repository, or other related resources.
Owner Selection:
Select the owner (administrator or user) who will manage this library. The dropdown list shows all available users, sorted by their email addresses. If no specific owner is needed, you can leave this field blank.
Ask a Question
This page allows you to ask a question and get an answer based on available libraries of knowledge. Here's how it works:
Ask a Question:
There is a text box where you can type your question. The placeholder text will give you examples of some topics the system can answer, based on the most frequently used libraries, such as specific subjects or categories.
Optional Library Selection:
You can limit the answers to a specific library if you want. This means you can choose a particular topic or area for your question, and the system will only look for answers in that library. If you're unsure, you can leave it as "optional," and the system will check all available sources.
Submit Your Question:
After typing your question, you can click the blue "Submit" button (which has an arrow icon) to send your question. The system will process your query and display the answer without refreshing the whole page, making it quicker and smoother.
This makes it easy to get answers quickly from a wide range of topics.
Assistants
The Assistant feature is designed to define Language Learning Model (LLM) assistants for specific topics. This form allows administrators or users to create, customize, and configure assistants according to their unique requirements. Below is an explanation of the fields and their purpose within the assistant creation form.
Fields
1. Status
Purpose: Defines the current status of the assistant.
Options:
Ready
Development
2. Owner (user_id)
Purpose: Assigns the owner of the assistant.
Type: Dropdown that displays users (emails) in the system.
Example: Select the appropriate user who will manage this assistant.
3. Name
Purpose: Specifies the name of the assistant.
Type: Text input.
Example: Provide a descriptive name for the assistant, such as "Healthcare Expert Assistant."
4. Quip URL
Purpose: Optional link to any relevant Quip document associated with the assistant.
Type: Text input.
Example: Add a Quip URL that holds documentation or collaboration content related to the assistant.
5. Confluence Spaces
Purpose: Lists the Confluence spaces that are associated with the assistant, if applicable.
Type: Text input.
Example: Enter space keys or names from Confluence for knowledge sharing related to the assistant.
6. Description
Purpose: Provides a detailed description of the assistant's purpose and functionality.
Type: Text area.
Example: A detailed explanation of what this assistant will help with, such as "This assistant answers common programming questions related to Ruby on Rails."
7. Libraries
Purpose: Lists the comma separated list of libraries the assistant will use.
Type: Text input.
Example: 2,3.
8. Input
Purpose: Describes the input that the assistant expects from the user.
Type: Text area.
Example: Describe what kind of input the assistant will work with, e.g., "natural language queries related to medical conditions."
9. Instructions
Purpose: Outlines any specific instructions on how the assistant will process the input.
Type: Text area.
Example: Define any special processing rules or behaviors, e.g., "translate medical terminology into layman's terms."
10. Output
Purpose: Describes the expected output or response that the assistant will provide.
Type: Text area.
Example: Specify the type of responses the assistant will generate, such as "detailed text responses to programming queries."
11. Context
Purpose: Defines the context or scope in which the assistant operates.
Type: Text area.
Example: "This assistant operates within the domain of healthcare research."
This structure provides flexibility in customizing assistants based on different user needs and topics, making it adaptable for various business or domain-specific requirements.
REST API
Questions
POST/api/v1/questionsCreate a new Question (Ask AI for answer)
Parameters
name
type
data type
description
question
required
text
The question to ask of the documentation
library_ids_included
optional
comma separated ids (reference to library)
The libraries to limit the answers
Responses
http code
content-type
response
201
text/plain;charset=UTF-8
JSON Object
400
application/json
{"code":"400","message":"Bad Request"}
Example cURL
curl-XPOST-H"Authorization: Bearer <token>"-H"Content-Type: application/json"-d'{"question": { "question" : "how do i setup falcon?", library_ids_included: ["1"] }}' http://localhost:3000/api/v1/questions
{"id": 226,"question": "how do i setup falcon?","status":"generating","answer": "# ANSWER\nTo set up Falcon, you need to install the Falcon CLI. Here are the steps to install the Falcon CLI:\n\n1. For macOS users, install the Falcon CLI with brew:\n ```\n brew tap sfdc-falcon/cli git[@git.soma.salesforce.com:sfdc-falcon/>homebrew-cli.git](https://git.soma.salesforce.com/git.soma.salesforce.com:sfdc-falcon/homebrew-cli.git)\n brew install falcon-cli\n ```\n\n2. For Linux users, install the Falcon CLI with `curl`:\n ```\n curl -sSL https://sfdc.co/get-falcon-cli | bash\n ```\n\n3. Verify that you've successfully installed the CLI by logging in:\n ```\n falcon login\n ```\n\nYou can find more information about setting up the Falcon CLI in the [Install the Falcon Command Line Interface (CLI)](https://git.soma.salesforce.com/tech-enablement/falcon-paved-path/blob/main/install-falcon-cli.md) document.\n\n# SOURCES\n- [Install the Falcon Command Line Interface (CLI)](https://git.soma.salesforce.com/tech-enablement/falcon-paved-path/blob/main/install-falcon-cli.md)","created_at": "2023-11-03T17:28:43.625Z","updated_at": "2023-11-03T17:28:43.625Z","library_ids_included": ["1"],"url": "http://localhost:3000/questions/226.json"}
GET/api/v1/questions/_id_Retrieve Question
Parameters
name
type
data type
description
Responses
name
type
data type
description
question
text
The question to ask of the documentation
status
pending, generating, generated, failed
The status of the generated answer. Poll every 5 seconds until the status is generated or failed.
able_to_answer
boolean
Was the GPT able to generate an answer? (true/false)
{"id": 226,"question": "how do i setup falcon?","status":"generated","answer": "# ANSWER\nTo set up Falcon, you need to install the Falcon CLI. Here are the steps to install the Falcon CLI:\n\n1. For macOS users, install the Falcon CLI with brew:\n ```\n brew tap sfdc-falcon/cli git[@git.soma.salesforce.com:sfdc-falcon/>homebrew-cli.git](https://git.soma.salesforce.com/git.soma.salesforce.com:sfdc-falcon/homebrew-cli.git)\n brew install falcon-cli\n ```\n\n2. For Linux users, install the Falcon CLI with `curl`:\n ```\n curl -sSL https://sfdc.co/get-falcon-cli | bash\n ```\n\n3. Verify that you've successfully installed the CLI by logging in:\n ```\n falcon login\n ```\n\nYou can find more information about setting up the Falcon CLI in the [Install the Falcon Command Line Interface (CLI)](https://git.soma.salesforce.com/tech-enablement/falcon-paved-path/blob/main/install-falcon-cli.md) document.\n\n# SOURCES\n- [Install the Falcon Command Line Interface (CLI)](https://git.soma.salesforce.com/tech-enablement/falcon-paved-path/blob/main/install-falcon-cli.md)","created_at": "2023-11-03T17:28:43.625Z","updated_at": "2023-11-03T17:28:43.625Z","url": "http://localhost:3000/questions/226.json"}
GET/api/v1/questionsList Questions
Parameters
name
type
data type
description
page
optional
integer
The page number to retrieve. Defaults to 1.
Responses
name
type
data type
description
questions
array
An array of question objects, each containing question details
Each object in the questions array includes:
name
type
data type
description
id
integer
The ID of the question
question
text
The content of the question
status
text
The status of the question (e.g., generated)
answer
text
The answer to the question
url
text
URL to access the question
created_at
datetime
The creation date and time of the question
updated_at
datetime
The last update date and time of the question
http code
content-type
response
200
application/json
JSON array of questions
400
application/json
{"code":"400","message":"Bad Request"}
Example cURL
curl -X GET -H "Authorization: Bearer <token>" "http://localhost:3000/api/v1/questions"
{"questions": [{"id": 226,"question": "how do i setup a new service?","status": "generated","answer": "# ANSWER\nTo set up ...","created_at": "2023-11-03T17:28:43.625Z","updated_at": "2023-11-03T17:28:43.625Z","url": "http://localhost:3000/questions/226.json"},{"id": 227,"question": "how do i use gen ai?","status": "generated","answer": "# ANSWER\n...","url": "http://localhost:3000/questions/227.json","created_at": "2023-11-14T01:55:11.731Z","updated_at": "2024-03-01T22:58:55.865Z"}]}
Documents
POST/api/v1/documentsCreate a new Document
Parameters
name
type
data type
description
document
required
text
The content of the document. 10,000 token limit.
title
required
text
The title of the document
library_id
required
text
The ID of the library to which this document will be added
external_id
optional
text
A unique ID provided by the client. If a POST request includes the same external_id as an existing record, the record will be updated instead of created.
Example POST Data
Make sure you have the top level "document" attribute.
"document": {"document": "Restart your computer to fix it.","title": "How to fix a computer","library_id": 23,}
curl -X GET -H "Authorization: Bearer <token>" http://localhost:3000/api/v1/documents/<id>
{
"id": 1,
"document": "# QUESTION\nHow do I use gen ai?\n\n# ANSWER\n...",
"title": "How do I use GenAI?",
"url": "http://localhost:3000/documents/1",
"length": 97,
"created_at": "2023-11-14T01:55:11.731Z",
"updated_at": "2024-03-01T22:58:55.865Z"
}
GET/api/v1/documentsList Documents
Parameters
name
type
data type
description
page
optional
integer
The page number to retrieve. Defaults to 1.
Responses
name
type
data type
description
documents
array
An array of document objects, each containing document details
Each object in the documents array includes:
name
type
data type
description
id
integer
The ID of the document
document
text
The content of the document
title
text
The title of the document
url
text
URL to access the document
created_at
datetime
The creation date and time of the document
updated_at
datetime
The last update date and time of the document
http code
content-type
response
200
application/json
JSON array of documents
400
application/json
{"code":"400","message":"Bad Request"}
Example cURL
curl -X GET -H "Authorization: Bearer <token>" "http://localhost:3000/api/v1/documents?page=1"
{"documents": [{"id": 1,"document": "# QUESTION\nHow do I use gen ai?\n\n# ANSWER\nThere is no direct answer provided in the conversation.","url": "http://localhost:3000/documents/1","created_at": "2023-11-14T01:55:11.731Z","updated_at": "2024-03-01T22:58:55.865Z"},{"id": 2,"document": "# QUESTION\nHow do I integrate API?\n\n# ANSWER\nTo integrate an API, first identify the API you need to integrate with...","url": "http://localhost:3000/documents/2","created_at": "2023-12-14T02:55:11.731Z","updated_at": "2024-01-02T23:58:55.865Z"}...]}
POST/api/v1/chats/:chat_id/messagesCreate a new Message
Parameters
name
type
data type
description
content
required
text
The content of the message
chat_id
required
integer
The ID of the chat this message belongs to
Responses
http code
content-type
response
201
application/json
JSON object containing the created message
400
application/json
{"code":"400","message":"Bad Request"}
Example cURL
curl-XPOST-H"Content-Type: application/json"-H"Authorization: Bearer <token>"-d'{"message": {"content":"Hello, how can I help you?", "chat_id": 1}}' http://localhost:3000/api/v1/chats/1/messages
{"id": 1,"content": "Hello, how can I help you?","chat_id": 1,"user_id": 1,"from": "user","created_at": "2023-11-15T20:17:25.665Z","updated_at": "2023-12-01T19:59:44.618Z"}
{"messages": [{"id": 1,"content": "Hello, how can I help you?","chat_id": 1,"user_id": 1,"from": "user","created_at": "2023-11-15T20:17:25.665Z","updated_at": "2023-12-01T19:59:44.618Z"},{"id": 2,"content": "I need help with setting up my environment","chat_id": 1,"user_id": 1,"from": "user","created_at": "2023-11-15T20:18:25.665Z","updated_at": "2023-12-01T19:59:44.618Z"}]}
DELETE/api/v1/chats/:chat_id/messages/:idDelete a Message
The MessagesChannel WebSocket API allows authenticated users to subscribe to a real-time messaging stream. Users must provide an authentication token to connect and stream messages from the channel.
WebSocket URL
To connect to the WebSocket API, use the following URL:
ws://yourserver.com/cable
Replace yourserver.com with the appropriate domain or IP where your Rails server is hosted.
Connection Steps
1. Establish the WebSocket Connection
To initiate a WebSocket connection, you must connect to the WebSocket endpoint and send a subscription request to the MessagesChannel with a valid token.
2. Using Native WebSocket API in JavaScript
If you want to use the native WebSocket API, here's how you can establish a connection and subscribe to the MessagesChannel:
constapiToken='your_api_token_here';// Establish WebSocket connectionconstws=newWebSocket('ws://yourserver.com/cable');ws.onopen=function(){console.log('Connected to WebSocket!');// Send a subscription request to the MessagesChannel with the tokenconstsubscriptionMessage={command: 'subscribe',identifier: JSON.stringify({channel: 'MessagesChannel',token: apiToken})};ws.send(JSON.stringify(subscriptionMessage));};ws.onmessage=function(event){constdata=JSON.parse(event.data);// Ignore ping messagesif(data.type==='ping')return;// Handle messages from the serverif(data.message){console.log('Received message:',data.message);}};ws.onerror=function(error){console.error('WebSocket error:',error);};ws.onclose=function(){console.log('Disconnected from WebSocket');};
3. Handling Subscription and Disconnection
When subscribing to the MessagesChannel, messages from the server will follow the standard ActionCable format. Incoming messages might look like: