Any way to make use of ImageClassificationInstance in C#? - c#

I keep getting Grpc.Core.RpcException: Status(StatusCode="Unimplemented" ... exception when I try to use the ImageClassificationInstance objects to classify using a model I have created in the Vertex AI. Is there any way (either by using Google AiPlatform library or using HttpRequest ) to perform ImageClassification with some given image?
The following is the code that I am using
var client = builder.Build();
var instance = new ImageClassificationPredictionInstance() { Content = rawdata };
var parameters = new ImageClassificationPredictionParams() { ConfidenceThreshold = 0.5f, MaxPredictions = 5 };
var pv = ValueConverter.ToValue(parameters);
var iv = new[] { ValueConverter.ToValue(instance) };
var ep = new EndpointName("My project ID", "us-central1", "My endpoint id"); // Of course I have set the string to my project ID and my endpoint ID
var returnobj = client.Predict(ep, iv, pv); // This is where the exception pops up
I can confirm that my vertex AI AutoML model is working on the web browser to classify any uploaded picture.

You must set Endpoint on PredictionServiceClientBuilder :
var client = new PredictionServiceClientBuilder
{
Endpoint = "us-central1-aiplatform.googleapis.com"
}.Build();

Related

Trying to use .HashSet from StackExchange.Redis for .NET and getting "Null value not valid in this context."

I have an api that returns values from the database to populate our footer dynamically. These footer values are stored as keys in Redis at the endpoint and then in the main application I'm getting the url of the current page and creating a Hash with the key being the current url and the 5 returned redis key/values from the api as HashEntries. I've shown the code below and right where the HashSet is (at the end) is where the error starts, but if I remove the cache.Hashset, the code runs fine. Do I need to prepopulate the hash or am I missing something obvious here?
//Get relative url after .com/
var url = HttpContext.Current.Request.Url.ToString();
var urlSplit = url.Split(new string[] { ".com/" }, StringSplitOptions.None);
var finalUrl = urlSplit[1];
//TODO: If url isn't in Redis, want to hit endpoint and load it into Redis
//in the background with worker service/async call.
var cache = RedisHelper.Connection.GetDatabase();
var hashExists = cache.HashExists(finalUrl, "footer:recent-content");
if (hashExists)
{
recentContent = cache.HashGet(finalUrl, "footer:recent-content");
topPages = cache.HashGet(finalUrl, "footer:top-pages");
featuredContent = cache.HashGet(finalUrl, "footer:featured-content");
topIntegrations = cache.HashGet(finalUrl, "footer:top-integrations");
featuredIntegrations = cache.HashGet(finalUrl, "footer:featured-integrations");
}
else
{
recentContent = cache.StringGet("footer:general:recent-content");
topPages = cache.StringGet("footer:general:top-pages");
featuredContent = cache.StringGet("footer:general:featured-content");
topIntegrations = cache.StringGet("footer:general:top-integrations");
featuredIntegrations = cache.StringGet("footer:general:featured-integrations");
HashEntry[] redisFooterHash =
{
new HashEntry("footer:recent-content", recentContent),
new HashEntry("footer:top-pages", topPages),
new HashEntry("footer:featured-content", featuredContent),
new HashEntry("footer:top-integrations", topIntegrations),
new HashEntry("footer:featured-integrations", featuredIntegrations)
};
cache.HashSet(finalUrl, redisFooterHash);
}
Also, the reason the keys are footer:recent-content and footer:general... is that in the future we want each page to have a dynamic footer based on it's content.

C# Authentication error in google dialogflow API

How do i fix this. I want to set my authentication in my code and not on the machine.
I have checked almost every answer on stackoverflow and github, but none has a good explanation.
How do i pass the credentials to the create intent, it throws this error.
InvalidOperationException: The Application Default Credentials are not available. They are available if running in Google Compute Engine. Otherwise, the environment variable GOOGLE_APPLICATION_CREDENTIALS must be defined pointing to a file defining the credentials. See https://developers.google.com/accounts/docs/application-default-credentials for more information.
GoogleCredential credential =
GoogleCredential.FromFile(file);
//var credential = GoogleCredential.FromStream(
// Assembly.GetExecutingAssembly().GetManifestResourceStream("chatbot-a90a9-8f2fb910202d.json"))
// .CreateScoped(IntentsClient.DefaultScopes);
var storage = StorageClient.Create(credential);
var client = IntentsClient.Create();
var text = new Intent.Types.Message.Types.Text();
text.Text_.Add("Message Text");
var message = new Intent.Types.Message()
{
Text = text
};
var trainingPhrasesParts = new List<string>
{
"Book a fligt",
"check cheap flights"
};
var phraseParts = new List<Intent.Types.TrainingPhrase.Types.Part>();
foreach (var part in trainingPhrasesParts)
{
phraseParts.Add(new Intent.Types.TrainingPhrase.Types.Part()
{
Text = part
});
}
var trainingPhrase = new Intent.Types.TrainingPhrase();
trainingPhrase.Parts.AddRange(phraseParts);
var intent = new Intent();
intent.DisplayName = "test";
intent.Messages.Add(message);
intent.TrainingPhrases.Add(trainingPhrase);
var newIntent = client.CreateIntent(
parent: new AgentName("chatbot-a90a9"),
intent: intent
);
SOLVED.
I change
var client = IntentsClient.Create();
To
IntentsClientBuilder builder = new IntentsClientBuilder
{
CredentialsPath = file, // Relative to where the code is executing or absolute path.
// Scopes = IntentsClient.DefaultScopes // Commented out because there's no need to specify this since you are using the defaults and all default values will be automatically used for values not specified in the builder.
};
IntentsClient client = builder.Build();

ElasticSearch.NET passing AWS Signature v4 in POST requests?

I am very new to ElasticSearch, and have set up an AWS Lambda function in c# to take the content of S3 object(s) (which contain JSON data) with the hopes of posting them to ES to be searchable.
I'm using the Elasticsearch.Net nuget library.
In the documentation here - https://github.com/elastic/elasticsearch-net there is samples of configuring the node URI etc, but my understanding is that any requests to ES need to be signed with AWS Signature V4 (based on Access/Secret key). I have created an IAM user for this purpose, but nowhere in the documentation can I find how to sign the POST requests. The samples show post methods, but no place to include the signature?
E.g.
var person = new Person
{
FirstName = "Martijn",
LastName = "Laarman"
};
var indexResponse = lowlevelClient.Index<BytesResponse>("people", "person", "1", PostData.Serializable(person));
byte[] responseBytes = indexResponse.Body;
var asyncIndexResponse = await lowlevelClient.IndexAsync<StringResponse>("people", "person", "1", PostData.Serializable(person));
string responseString = asyncIndexResponse.Body;
Even when instantiating the connection, nowhere is there a place to add your credentials?
var settings = new ConnectionConfiguration(new Uri("http://example.com:9200"))
.RequestTimeout(TimeSpan.FromMinutes(2));
var lowlevelClient = new ElasticLowLevelClient(settings);
I have checked ConnectionConfiguration object but there's no methods or properties that seem related. What have I missed?
Using the elasticsearch-net-aws package you should be able to set up the low level client like so:
var httpConnection = new AwsHttpConnection("us-east-1"); // or whatever region you're using
var pool = new SingleNodeConnectionPool(new Uri(TestConfig.Endpoint));
var config = new ConnectionConfiguration(pool, httpConnection);
config.DisableDirectStreaming();
var client = new ElasticLowLevelClient(config);
// ...
// if using an access key
var httpConnection = new AwsHttpConnection("us-east-1", new StaticCredentialsProvider(new AwsCredentials
{
AccessKey = "My AWS access key",
SecretKey = "My AWS secret key",
}));
// if using app.config, environment variables, or roles
var httpConnection = new AwsHttpConnection("us-east-1");
var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
var config = new ConnectionSettings(pool, httpConnection);
var client = new ElasticClient(config);

AdWords API in ASP.NET. Can I avoid using the `user` object?

The story is: I am building a Node application, but I need data from Google AdWords. Since there is no official Node library and I couldn't get the unofficial ones to work I wanted to create a REST API in ASP.NET. So far this is what I have:
[HttpGet]
public IEnumerable<string> Get()
{
TargetingIdeaSelector selector = new TargetingIdeaSelector
{
requestType = RequestType.IDEAS,
ideaType = IdeaType.KEYWORD,
requestedAttributeTypes = new AttributeType[] {
AttributeType.KEYWORD_TEXT,
AttributeType.SEARCH_VOLUME,
AttributeType.AVERAGE_CPC,
AttributeType.COMPETITION,
AttributeType.CATEGORY_PRODUCTS_AND_SERVICES
}
};
// Set selector paging (required for targeting idea service).
Paging paging = Paging.Default;
// Create related to query search parameter.
RelatedToQuerySearchParameter relatedToQuerySearchParameter =
new RelatedToQuerySearchParameter
{
queries = new String[] {
"bakery", "pastries", "birthday cake"
}
};
var searchParameters = new List<SearchParameter>
{
relatedToQuerySearchParameter
};
TargetingIdeaPage page = new TargetingIdeaPage();
page = targetingIdeaService.get(selector);
return new string[] { "value1", "value2" };
}
I basically grabbed the code from the docs. The problem is that the targetingIdeaService is not defined. If I try to take a look at a code sample it looks like this:
public void Run(AdWordsUser user, long? adGroupId) {
using (TargetingIdeaService targetingIdeaService =
(TargetingIdeaService) user.GetService(AdWordsService.v201802.TargetingIdeaService)) {
// Create selector.
TargetingIdeaSelector selector = new TargetingIdeaSelector();
selector.requestType = RequestType.IDEAS;
selector.ideaType = IdeaType.KEYWORD;
selector.requestedAttributeTypes = new AttributeType[] {
AttributeType.KEYWORD_TEXT,
AttributeType.SEARCH_VOLUME,
AttributeType.AVERAGE_CPC,
AttributeType.COMPETITION,
AttributeType.CATEGORY_PRODUCTS_AND_SERVICES
};
List<SearchParameter> searchParameters = new List<SearchParameter>();
// Create related to query search parameter.
RelatedToQuerySearchParameter relatedToQuerySearchParameter =
new RelatedToQuerySearchParameter();
relatedToQuerySearchParameter.queries = new String[] {
"bakery", "pastries", "birthday cake"
};
searchParameters.Add(relatedToQuerySearchParameter);
And a lot more code. The point is they made it in a function, and are passing a user object into it. Now I will not have said object. Unless it's needed. Then I'm screwed. But I need to get this service up and running. This is the only missing step, other than that it should work.
So my question is: Does anyone see a way around it?
The AdWordsUser object contains the authentication you need to connect to the API. Without it your app will have no idea of which AdWords account and OAuth refresh token to supply to the TargetingIdeaService.

Add List instead of Replace List for TableView DataSource

I am currently trying to add pagination to my Instagram App and have managed to replace the List that provides the Data Source with the new data, but I want to add it to the existing List so that when I scroll back up it would show the most recent picture. Here is my approach right now:
var request = new RestRequest { RootElement = "data", Resource = "/users/self/feed" };
request.AddParameter ("access_token", instagramAccessToken);
var client = new RestClient ("https://api.instagram.com/v1");
client.ExecuteAsync (request, response => {
var rootObject = JsonConvert.DeserializeObject<RootObject> (response.Content);
string nextURL = rootObject.pagination.next_url;
//// Create Next Client
var requestBack = new RestRequest ();
var clientBack = new RestClient (nextURL);
// GET Next Response
clientBack.ExecuteAsync(requestBack, responseBack => {
var rootObjectBack = JsonConvert.DeserializeObject<RootObject> (responseBack.Content);
table.InvokeOnMainThread (() => {
// Create list that contains newly attained JSON
List<Datum> instagramData = rootObjectBack.data;
// Create dummy list for other values
List<Datum> sloppy = null;
// Send list that contains data, and the sloppy which doesnt contain anything to the Facebook and Twitter Values.
table.Source = new TableSource<Datum>(instagramData, sloppy, sloppy);
table.ReloadData ();
});
});
});
List<x> A = initial data
List<x> B = new data
A.AddRange(B);
A now has B appended to the end
to access the public List (assuming it's called "Data") inside of your existing source
((TableSource<Datum>)table.Source).Data

Categories

Resources